[java-identity-provider] branch master updated: IDP-1434 - Redesign Attribute encoding/decoding as a service
Scott Cantor
cantor.2 at osu.edu
Mon May 13 13:39:56 EDT 2019
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=0353832c821a21a870bba5845ec0ead1b61aedf1
The following commit(s) were added to refs/heads/master by this push:
new 0353832 IDP-1434 - Redesign Attribute encoding/decoding as a service
0353832 is described below
commit 0353832c821a21a870bba5845ec0ead1b61aedf1
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon May 13 13:39:51 2019 -0400
IDP-1434 - Redesign Attribute encoding/decoding as a service
https://issues.shibboleth.net/jira/browse/IDP-1434
Squashed commit from feature/IDP-1434.
---
idp-admin-api/.project | 5 -
idp-admin-impl/.project | 5 -
idp-attribute-api/.project | 5 -
.../idp/attribute/AttributeDecodingException.java | 62 +++
.../shibboleth/idp/attribute/AttributeEncoder.java | 71 ----
.../net/shibboleth/idp/attribute/IdPAttribute.java | 33 +-
.../transcoding/AbstractAttributeTranscoder.java | 156 ++++++++
.../attribute/transcoding/AttributeTranscoder.java | 98 +++++
.../transcoding/AttributeTranscoderRegistry.java | 85 ++++
.../attribute/transcoding/TranscoderSupport.java | 55 +++
.../idp/attribute/transcoding/TranscodingRule.java | 160 ++++++++
.../idp/attribute/transcoding}/package-info.java | 5 +-
.../shibboleth/idp/attribute/AttributeTest.java | 63 ---
.../net/shibboleth/idp/attribute/MockEncoder.java | 70 ----
idp-attribute-filter-api/.project | 5 -
idp-attribute-filter-impl/.project | 5 -
.../saml/impl/AttributeInMetadataMatcher.java | 165 +++++---
.../impl/MappedAttributeInMetadataMatcher.java | 261 -------------
.../saml/impl/AttributeInMetadataMatcherTest.java | 26 +-
.../impl/MappedAttributeInMetadataMatcherTest.java | 12 +-
idp-attribute-filter-spring/.project | 5 -
.../impl/MappedAttributeInMetadataRuleParser.java | 14 +-
.../MappedAttributeInMetadataRuleParserTest.java | 6 +-
idp-attribute-impl/.project | 5 -
idp-attribute-impl/pom.xml | 6 +
.../impl/AttributeTranscoderRegistryImpl.java | 357 +++++++++++++++++
.../transcoding/impl/TranscodingRuleLoader.java | 95 +++++
.../attribute/transcoding/impl}/package-info.java | 5 +-
.../impl/AttributeTranscoderRegistryImplTest.java | 338 ++++++++++++++++
.../attribute/transcoding/impl/PairTranscoder.java | 102 +++++
idp-attribute-resolver-api/.project | 5 -
.../resolver/AbstractAttributeDefinition.java | 38 --
.../attribute/resolver/AttributeDefinition.java | 10 -
.../idp/attribute/resolver/AttributeResolver.java | 12 -
.../resolver/ResolvedAttributeDefinition.java | 6 -
.../resolver/AbstractAttributeDefinitionTest.java | 72 ----
.../attribute/resolver/MockAttributeEncoder.java | 66 ----
idp-attribute-resolver-impl/.project | 5 -
.../resolver/impl/AttributeResolverImpl.java | 13 -
idp-attribute-resolver-spring/.project | 5 -
.../spring/ad/BaseAttributeDefinitionParser.java | 11 -
.../spring/enc/BaseAttributeEncoderParser.java | 104 ++---
.../enc/BaseSAML1AttributeEncoderParser.java | 61 +++
.../enc/BaseSAML2AttributeEncoderParser.java | 65 ++++
.../enc/BaseScopedAttributeEncoderParser.java | 59 ---
.../impl/SAML1Base64AttributeEncoderParser.java | 39 +-
.../SAML1ScopedStringAttributeEncoderParser.java | 56 +--
.../impl/SAML1StringAttributeEncoderParser.java | 45 +--
.../impl/SAML1XMLObjectAttributeEncoderParser.java | 39 +-
.../impl/SAML2Base64AttributeEncoderParser.java | 44 +--
.../SAML2ScopedStringAttributeEncoderParser.java | 59 ++-
.../impl/SAML2StringAttributeEncoderParser.java | 45 +--
.../impl/SAML2XMLObjectAttributeEncoderParser.java | 45 +--
.../spring/impl/AttributeResolverParser.java | 22 +-
.../impl/AttributeRegistryServiceStrategy.java | 100 +++++
.../transcoding/spring/impl}/package-info.java | 6 +-
.../resolver/spring/AttributeMapperTest.java | 56 ++-
.../spring/AttributeMappingNodeProcessorTest.java | 21 +-
.../spring/BaseAttributeDefinitionParserTest.java | 22 +-
.../spring/BaseEncoderDefinitionParserTest.java | 104 +++++
.../spring/ad/SimpleAttributeParserTest.java | 37 +-
.../attribute/resolver/spring/enc/Regressions.java | 20 +-
.../enc/SAML1Base64AttributeEncoderParserTest.java | 42 +-
...AML1ScopedStringAttributeEncoderParserTest.java | 61 +--
.../enc/SAML1StringAttributeEncoderParserTest.java | 45 ++-
.../SAML1XMLObjectAttributeEncoderParserTest.java | 44 ++-
.../enc/SAML2Base64AttributeEncoderParserTest.java | 45 ++-
...AML2ScopedStringAttributeEncoderParserTest.java | 63 +--
.../enc/SAML2StringAttributeEncoderParserTest.java | 76 ++--
.../SAML2XMLObjectAttributeEncoderParserTest.java | 48 ++-
.../src/test/resources/logback-test.xml | 3 +
.../idp/attribute/resolver/filter/service.xml | 52 ++-
.../idp/attribute/resolver/spring/customBean.xml | 28 +-
.../attribute/resolver/spring/enc/predicates.xml | 10 -
.../resolver/spring/enc/resolver/idp-571.xml | 3 -
.../resolver/spring/enc/resolver/saml1Base64.xml | 11 +-
.../spring/enc/resolver/saml1Base64Default.xml | 4 +-
.../resolver/spring/enc/resolver/saml1Scoped.xml | 9 +-
.../spring/enc/resolver/saml1ScopedDefault.xml | 3 +-
.../resolver/spring/enc/resolver/saml1String.xml | 11 +-
.../spring/enc/resolver/saml1StringDefault.xml | 3 +-
.../spring/enc/resolver/saml1XmlObject.xml | 11 +-
.../spring/enc/resolver/saml1XmlObjectDefault.xml | 1 +
.../resolver/spring/enc/resolver/saml2Base64.xml | 10 +-
.../spring/enc/resolver/saml2Base64Default.xml | 1 +
.../resolver/spring/enc/resolver/saml2Scoped.xml | 10 +-
.../spring/enc/resolver/saml2ScopedDefault.xml | 1 +
.../spring/enc/resolver/saml2ScopedNoName.xml | 13 +-
.../resolver/spring/enc/resolver/saml2String.xml | 8 +-
.../spring/enc/resolver/saml2StringConditional.xml | 2 +-
.../spring/enc/resolver/saml2StringDefault.xml | 1 +
.../spring/enc/resolver/saml2XmlObject.xml | 11 +-
.../spring/enc/resolver/saml2XmlObjectDefault.xml | 1 +
.../resolver/spring/mapperTest-attributes.xml | 42 +-
.../idp/attribute/resolver/spring/mapperTest.xml | 26 +-
idp-authn-api/.project | 5 -
idp-authn-impl/.project | 5 -
idp-bom/.project | 5 -
idp-cas-api/.project | 5 -
idp-cas-impl/.project | 5 -
idp-conf/.project | 5 -
.../attributes/saml1/eduPersonPrincipalName.txt | 4 +
.../saml1/eduPersonScopedAffiliation.txt | 4 +
.../src/main/resources/attributes/saml1/mail.txt | 4 +
.../src/main/resources/attributes/saml1/uid.txt | 4 +
.../attributes/saml2/eduPersonPrincipalName.txt | 4 +
.../saml2/eduPersonScopedAffiliation.txt | 4 +
.../src/main/resources/attributes/saml2/mail.txt | 4 +
.../src/main/resources/attributes/saml2/uid.txt | 4 +
.../src/main/resources/conf/attribute-registry.xml | 16 +-
.../src/main/resources/conf/attribute-resolver.xml | 11 +-
.../src/main/resources/conf/services.properties | 5 +
idp-conf/src/main/resources/conf/services.xml | 12 +
.../system/conf/attribute-registry-system.xml | 48 +++
.../main/resources/system/conf/services-system.xml | 32 +-
.../resources/system/flows/admin/status-beans.xml | 1 +
.../system/flows/saml/saml-abstract-beans.xml | 10 +-
.../flows/saml/saml1/attribute-query-beans.xml | 4 +
.../system/flows/saml/saml1/common-beans.xml | 3 +-
.../flows/saml/saml2/attribute-query-beans.xml | 4 +
.../system/flows/saml/saml2/common-beans.xml | 3 +-
.../idp/test/flows/mapper/MappingTest.java | 2 +-
.../idp/test/flows/mapper/TestAfterFilter.java | 8 +-
.../flows/saml1/SAML1AttributeQueryFlowTest.java | 2 +-
.../flows/saml2/SAML2AttributeQueryFlowTest.java | 2 +-
.../resources/mapping/configs/attribute-filter.xml | 2 +-
.../mapping/configs/attribute-resolver.xml | 2 -
.../test/resources/mapping/configs/override.xml | 5 +
idp-consent-api/.project | 5 -
idp-consent-impl/.project | 5 -
.../logic/impl/IsAttributeRequiredPredicate.java | 2 +-
idp-core/.project | 5 -
idp-installer/.project | 5 -
idp-profile-api/.project | 5 -
idp-profile-impl/.project | 5 -
idp-profile-spring/.project | 5 -
.../NodeProcessingAttachingBeanPostProcessor.java | 14 +-
idp-saml-api/.project | 5 -
idp-saml-api/pom.xml | 1 -
.../encoding/AbstractSAML1AttributeEncoder.java | 158 --------
.../encoding/AbstractSAML2AttributeEncoder.java | 166 --------
.../encoding/AbstractSAMLAttributeEncoder.java | 258 -------------
.../AttributeDesignatorMapperProcessor.java | 44 ---
.../encoding/AttributeMapperProcessor.java | 47 ---
.../attribute/encoding/SAML1AttributeEncoder.java | 48 ---
.../AbstractSAMLAttributeDesignatorMapper.java | 258 -------------
.../AbstractSAMLAttributeDesignatorsMapper.java | 187 ---------
.../mapping/AbstractSAMLAttributeMapper.java | 309 ---------------
.../mapping/AbstractSAMLAttributeValueMapper.java | 204 ----------
.../mapping/AbstractSAMLAttributesMapper.java | 191 ---------
.../saml/attribute/mapping/AttributeMapper.java | 49 ---
.../saml/attribute/mapping/AttributesMapper.java | 49 ---
.../AbstractSAML1AttributeTranscoder.java | 187 +++++++++
.../AbstractSAML2AttributeTranscoder.java | 188 +++++++++
.../AbstractSAMLAttributeTranscoder.java | 285 ++++++++++++++
.../AttributesMapContainer.java | 16 +-
.../transcoding/SAML1AttributeTranscoder.java | 27 +-
.../SAML2AttributeTranscoder.java} | 37 +-
.../transcoding/SAMLAttributeTranscoder.java | 31 +-
.../SAMLEncoderSupport.java | 2 +-
.../{encoding => transcoding}/package-info.java | 4 +-
.../AbstractSAML1AttributeEncoderTest.java | 94 -----
.../AbstractSAML2AttributeEncoderTest.java | 143 -------
.../encoding/AbstractSAMLAttributeEncoderTest.java | 229 -----------
.../SAMLEncoderSupportTest.java | 2 +-
idp-saml-impl/.project | 5 -
.../encoding/impl/SAML1ByteAttributeEncoder.java | 52 ---
.../impl/SAML1ScopedStringAttributeEncoder.java | 176 ---------
.../impl/SAML1XMLObjectAttributeEncoder.java | 52 ---
.../encoding/impl/SAML2ByteAttributeEncoder.java | 67 ----
.../impl/SAML2ScopedStringAttributeEncoder.java | 192 ---------
.../impl/SAML2XMLObjectAttributeEncoder.java | 69 ----
.../mapping/impl/ByteAttributeValueMapper.java | 52 ---
.../mapping/impl/RequestedAttributeMapper.java | 40 --
.../mapping/impl/RequestedAttributesMapper.java | 60 ---
.../impl/SAML1AttributeDesignatorsMapper.java | 58 ---
.../SAML1AttributeDesignatorsMapperService.java | 140 -------
.../mapping/impl/SAML2AttributesMapper.java | 60 ---
.../mapping/impl/SAML2AttributesMapperService.java | 138 -------
.../impl/ScopedStringAttributeValueMapper.java | 110 ------
.../mapping/impl/StringAttributeValueMapper.java | 49 ---
.../impl/XMLObjectAttributeValueMapper.java | 112 ------
.../impl/SAML1ByteAttributeTranscoder.java | 84 ++++
.../impl/SAML1ScopedStringAttributeTranscoder.java | 134 +++++++
.../impl/SAML1StringAttributeTranscoder.java} | 44 ++-
.../impl/SAML1XMLObjectAttributeTranscoder.java | 97 +++++
.../impl/SAML2ByteAttributeTranscoder.java | 84 ++++
.../impl/SAML2ScopedStringAttributeTranscoder.java | 135 +++++++
.../impl/SAML2StringAttributeTranscoder.java} | 48 +--
.../impl/SAML2XMLObjectAttributeTranscoder.java | 97 +++++
.../impl/package-info.java | 6 +-
.../impl/AttributeMappingNodeProcessor.java | 232 +++++------
.../impl/BaseAddAttributeStatementToAssertion.java | 97 ++++-
.../impl/AddAttributeStatementToAssertion.java | 63 ++-
.../impl/FilterByQueriedAttributeDesignators.java | 118 +++++-
.../impl/AddAttributeStatementToAssertion.java | 61 ++-
.../profile/impl/FilterByQueriedAttributes.java | 109 +++++-
...estedAttributesInAttributeConsumingService.java | 33 +-
.../impl/SAML1ByteAttributeEncoderTest.java | 168 --------
.../SAML1ScopedStringAttributeEncoderTest.java | 288 --------------
.../impl/SAML1StringAttributeEncoderTest.java | 143 -------
.../impl/SAML1XMLObjectAttributeEncoderTest.java | 188 ---------
.../impl/SAML2ByteAttributeEncoderTest.java | 161 --------
.../SAML2ScopedStringAttributeEncoderTest.java | 290 --------------
.../impl/SAML2StringAttributeEncoderTest.java | 140 -------
.../impl/SAML2XMLObjectAttributeEncoderTest.java | 189 ---------
.../mapping/impl/AttributeValueMapperTest.java | 141 -------
.../saml/attribute/mapping/impl/MappingTests.java | 49 ---
.../attribute/mapping/impl/NativeSpringTest.java | 63 ---
.../mapping/impl/RequestedAttributeMapperTest.java | 163 --------
.../impl/RequestedAttributesMapperTest.java | 85 ----
.../impl/SAML1ByteAttributeTranscoderTest.java | 368 ++++++++++++++++++
.../SAML1ScopedStringAttributeTranscoderTest.java | 370 ++++++++++++++++++
.../impl/SAML1StringAttributeTranscoderTest.java | 327 ++++++++++++++++
.../impl/SAML2ByteAttributeTranscoderTest.java | 405 +++++++++++++++++++
.../SAML2ScopedStringAttributeTranscoderTest.java | 394 +++++++++++++++++++
.../impl/SAML2StringAttributeTranscoderTest.java | 364 +++++++++++++++++
.../SAML2XMLObjectAttributeTranscoderTest.java | 429 +++++++++++++++++++++
.../impl/AddAttributeStatementToAssertionTest.java | 152 ++++++--
.../FilterByQueriedAttributeDesignatorsTest.java | 71 +++-
.../impl/AddAttributeStatementToAssertionTest.java | 152 ++++++--
.../impl/FilterByQueriedAttributesTest.java | 59 ++-
.../impl/attribute/mapping/attributesMapper.xml | 107 -----
.../attribute/mapping/requestedAttributeValues.xml | 50 ---
.../idp/saml/impl/profile/AttributeQuery.xml | 11 +-
.../idp/saml/impl/profile/AttributeQuerySaml1.xml | 25 +-
.../idp/saml/impl/profile/saml1Mapper.xml | 156 ++++----
.../idp/saml/impl/profile/saml2Mapper.xml | 173 ++++-----
idp-schema/.project | 5 -
.../src/main/resources/schema/shibboleth-afp.xsd | 44 +--
idp-session-api/.project | 5 -
idp-session-impl/.project | 5 -
idp-ui/.project | 5 -
idp-war/.project | 5 -
idp-war/src/main/webapp/WEB-INF/jsp/status.jsp | 1 +
235 files changed, 7864 insertions(+), 8536 deletions(-)
diff --git a/idp-admin-api/.project b/idp-admin-api/.project
index 4efaa10..9dbebd9 100644
--- a/idp-admin-api/.project
+++ b/idp-admin-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-admin-impl/.project b/idp-admin-impl/.project
index 90b3f69..e76252e 100644
--- a/idp-admin-impl/.project
+++ b/idp-admin-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-attribute-api/.project b/idp-attribute-api/.project
index ed92a0d..733bbbb 100644
--- a/idp-attribute-api/.project
+++ b/idp-attribute-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/AttributeDecodingException.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/AttributeDecodingException.java
new file mode 100644
index 0000000..ea56273
--- /dev/null
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/AttributeDecodingException.java
@@ -0,0 +1,62 @@
+/*
+ * 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.idp.attribute;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+/** Indicates a problem during decoding into an attribute. */
+ at ThreadSafe
+public class AttributeDecodingException extends AttributeException {
+
+ /** Serialization ID. */
+ private static final long serialVersionUID = -7129079905857690466L;
+
+ /** Constructor. */
+ public AttributeDecodingException() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message exception message
+ */
+ public AttributeDecodingException(@Nullable final String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param wrappedException exception to be wrapped by this one
+ */
+ public AttributeDecodingException(@Nullable final Exception wrappedException) {
+ super(wrappedException);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message exception message
+ * @param wrappedException exception to be wrapped by this one
+ */
+ public AttributeDecodingException(@Nullable final String message, @Nullable final Exception wrappedException) {
+ super(message, wrappedException);
+ }
+}
\ No newline at end of file
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/AttributeEncoder.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/AttributeEncoder.java
deleted file mode 100644
index f72b56b..0000000
--- a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/AttributeEncoder.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.idp.attribute;
-
-import java.util.function.Predicate;
-
-import javax.annotation.Nonnull;
-import javax.annotation.concurrent.ThreadSafe;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-
-/**
- * Attribute encoders convert an {@link IdPAttribute} into a protocol specific representation. Implementations must take
- * into account that an {@link IdPAttribute} may contain values of multiple types. An implementation encountering
- * a value type it does not understand may either decide to ignore it or throw an {@link AttributeEncodingException}.
- *
- * <p>Encoders implement a {@link Predicate} interface to determine their applicability to a request.</p>
- *
- * <p>Encoders <strong>MUST</strong> be thread-safe and stateless and <strong>MUST</strong> implement appropriate
- * {@link Object#equals(Object)} and {@link Object#hashCode()} methods.</p>
- *
- * @param <EncodedType> the type of object created by encoding the attribute
- */
- at ThreadSafe
-public interface AttributeEncoder<EncodedType> {
-
- /**
- * Get the identifier of the protocol targeted by this encoder. Note, some protocols may have different types of
- * encoders that are used to encode attributes in to different parts of the protocol message. This identifier should
- * not be used to distinguish between the different message structure, it should only identify the protocol itself.
- *
- * @return identifier of the protocol targeted by this encounter
- */
- @Nonnull @NotEmpty String getProtocol();
-
- /**
- * Get an activation condition for this encoder.
- *
- * @return a predicate indicating whether the encoder should be applied
- */
- @Nonnull Predicate<ProfileRequestContext> getActivationCondition();
-
- /**
- * Encode the supplied attribute into a protocol specific representation.
- *
- * @param attribute the attribute to encode
- *
- * @return the Object the attribute was encoded into
- *
- * @throws AttributeEncodingException if unable to successfully encode attribute
- */
- @Nonnull EncodedType encode(@Nonnull final IdPAttribute attribute) throws AttributeEncodingException;
-
-}
\ No newline at end of file
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/IdPAttribute.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/IdPAttribute.java
index 3825d4f..56194f5 100644
--- a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/IdPAttribute.java
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/IdPAttribute.java
@@ -23,7 +23,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
@@ -32,10 +31,7 @@ import javax.annotation.concurrent.NotThreadSafe;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
import net.shibboleth.idp.attribute.EmptyAttributeValue.EmptyType;
import net.shibboleth.utilities.java.support.annotation.ParameterName;
@@ -69,9 +65,6 @@ public class IdPAttribute implements Comparable<IdPAttribute>, Cloneable {
/** Values for this attribute. */
@Nonnull private List<IdPAttributeValue<?>> values;
- /** Encoders that may be used to encode this attribute. */
- @Nonnull private Set<AttributeEncoder<?>> encoders;
-
/**
* Constructor.
*
@@ -86,7 +79,6 @@ public class IdPAttribute implements Comparable<IdPAttribute>, Cloneable {
displayDescriptions = Collections.emptyMap();
values = Collections.emptyList();
- encoders = Collections.emptySet();
}
/**
@@ -183,28 +175,6 @@ public class IdPAttribute implements Comparable<IdPAttribute>, Cloneable {
}
}
- /**
- * Gets the list of attribute encoders usable with this attribute.
- *
- * @return attribute encoders usable with this attribute
- */
- @Nonnull @NonnullElements @Unmodifiable @NotLive public Set<AttributeEncoder<?>> getEncoders() {
- return encoders;
- }
-
- /**
- * Replaces the existing encoders for this attribute with the given encoders.
- *
- * @param newEncoders the new encoders for this attribute
- */
- public void setEncoders(@Nullable @NullableElements final Collection<AttributeEncoder<?>> newEncoders) {
- if (newEncoders != null) {
- encoders = ImmutableSet.copyOf(Collections2.filter(newEncoders, Predicates.notNull()));
- } else {
- encoders = ImmutableSet.of();
- }
- }
-
/** {@inheritDoc} */
@Override
public int compareTo(final IdPAttribute other) {
@@ -222,7 +192,6 @@ public class IdPAttribute implements Comparable<IdPAttribute>, Cloneable {
final IdPAttribute clone = (IdPAttribute) super.clone();
clone.setDisplayDescriptions(getDisplayDescriptions());
clone.setDisplayNames(getDisplayNames());
- clone.setEncoders(getEncoders());
clone.setValues(getValues());
return clone;
}
@@ -256,7 +225,7 @@ public class IdPAttribute implements Comparable<IdPAttribute>, Cloneable {
@Override
@Nonnull public String toString() {
return MoreObjects.toStringHelper(this).add("id", getId()).add("displayNames", displayNames)
- .add("displayDescriptions", displayDescriptions).add("encoders", encoders).add("values", values)
+ .add("displayDescriptions", displayDescriptions).add("values", values)
.toString();
}
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java
new file mode 100644
index 0000000..14a2500
--- /dev/null
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java
@@ -0,0 +1,156 @@
+/*
+ * 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.idp.attribute.transcoding;
+
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Predicates;
+
+/**
+ * Base class for transcoders.
+ *
+ * @param <T> type of object supported
+ */
+public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializableComponent
+ implements AttributeTranscoder<T> {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractAttributeTranscoder.class);
+
+ /** Condition for use of this transcoder. */
+ @Nonnull private Predicate<ProfileRequestContext> activationCondition;
+
+ /** Constructor. */
+ public AbstractAttributeTranscoder() {
+ activationCondition = Predicates.alwaysTrue();
+ }
+
+ /**
+ * Set an activation condition for this transcoder.
+ *
+ * @param condition condition to set
+ */
+ public void setActivationCondition(@Nonnull final Predicate<ProfileRequestContext> condition) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ activationCondition = Constraint.isNotNull(condition, "Activation condition cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Nullable public T encode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends T> to,
+ @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+ Constraint.isNotNull(attribute, "Attribute to encode cannot be null");
+
+ if (!checkActivation(profileRequestContext, rule)) {
+ return null;
+ }
+
+ return doEncode(profileRequestContext, attribute, to, rule);
+ }
+
+ /** {@inheritDoc} */
+ @Nullable public IdPAttribute decode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final T input, @Nonnull final TranscodingRule rule) throws AttributeDecodingException {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+ Constraint.isNotNull(input, "Attribute to decode cannot be null");
+
+ if (!checkActivation(profileRequestContext, rule)) {
+ return null;
+ }
+
+ return doDecode(profileRequestContext, input, rule);
+ }
+
+
+ /**
+ * Encode the supplied attribute into a protocol specific representation.
+ *
+ * @param profileRequestContext current profile request context
+ * @param attribute the attribute to encode
+ * @param to specific type of object to encode
+ * @param rule properties governing the encoding process, principally the resulting object's naming
+ *
+ * @return the Object the attribute was encoded into
+ *
+ * @throws AttributeEncodingException if unable to successfully encode attribute
+ */
+ @Nullable protected abstract T doEncode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends T> to,
+ @Nonnull final TranscodingRule rule) throws AttributeEncodingException;
+
+
+ /**
+ * Decode the supplied object into a protocol-neutral representation.
+ *
+ * @param profileRequestContext current profile request context
+ * @param input the object to decode
+ * @param rule properties governing the decoding process, principally the resulting attribute's naming
+ *
+ * @return the attribute the object was decoded into
+ *
+ * @throws AttributeDecodingException if unable to successfully decode object
+ */
+ @Nullable protected abstract IdPAttribute doDecode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final T input, @Nonnull final TranscodingRule rule) throws AttributeDecodingException;
+
+
+ /**
+ *
+ * Apply any activation rules to the request.
+ *
+ * @param profileRequestContext current profile request context
+ * @param rule properties governing the transoding process
+ *
+ * @return true iff the process should continue
+ */
+ private boolean checkActivation(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final TranscodingRule rule) {
+
+ if (!activationCondition.test(profileRequestContext)) {
+ log.debug("Transcoder inactive");
+ return false;
+ }
+
+ final Predicate condition = rule.get(AttributeTranscoderRegistry.PROP_CONDITION, Predicate.class);
+ if (condition != null) {
+ if (!condition.test(profileRequestContext)) {
+ log.debug("Transcoder inactive");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoder.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoder.java
new file mode 100644
index 0000000..a8a0a2f
--- /dev/null
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoder.java
@@ -0,0 +1,98 @@
+/*
+ * 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.idp.attribute.transcoding;
+
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.InitializableComponent;
+
+/**
+ * Transcoders are objects that support both attribute encoding and decoding for bidirectional
+ * translation between {@link IdPAttribute} format and technology-specific formats.
+ *
+ * <p>Implementations must take into account values of multiple types. An implementation encountering
+ * a value type it does not understand may either decide to ignore it or throw exceptions.</p>
+ *
+ * <p>Transcoders implement a {@link Predicate} interface to determine their applicability to a request.</p>
+ *
+ * <p>Transcoders <strong>MUST</strong> be thread-safe and stateless.</p>
+ *
+ * @param <T> the type of object supported
+ */
+ at ThreadSafe
+public interface AttributeTranscoder<T> extends InitializableComponent {
+
+ /**
+ * Get the class representing the type of object supported by this transcoder.
+ *
+ * @return object type supported
+ */
+ @Nonnull Class<T> getEncodedType();
+
+ /**
+ * Get the name of the encoded object that would be created by a given set of
+ * instructions.
+ *
+ * @param rule properties governing the encoding process
+ *
+ * @return a canonical name for objects produced by this transcoder for the
+ * given instructions
+ */
+ @Nullable @NotEmpty String getEncodedName(@Nonnull final TranscodingRule rule);
+
+ /**
+ * Encode the supplied attribute into a protocol specific representation.
+ *
+ * @param profileRequestContext current profile request context
+ * @param attribute the attribute to encode
+ * @param to specific type of object to encode
+ * @param rule properties governing the encoding process, principally the resulting object's naming
+ *
+ * @return the Object the attribute was encoded into
+ *
+ * @throws AttributeEncodingException if unable to successfully encode attribute
+ */
+ @Nullable T encode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends T> to,
+ @Nonnull final TranscodingRule rule) throws AttributeEncodingException;
+
+ /**
+ * Decode the supplied object into a protocol-neutral representation.
+ *
+ * @param profileRequestContext current profile request context
+ * @param input the object to decode
+ * @param rule properties governing the decoding process, principally the resulting attribute's naming
+ *
+ * @return the attribute the object was decoded into
+ *
+ * @throws AttributeDecodingException if unable to successfully decode object
+ */
+ @Nullable IdPAttribute decode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final T input, @Nonnull final TranscodingRule rule) throws AttributeDecodingException;
+
+}
\ No newline at end of file
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoderRegistry.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoderRegistry.java
new file mode 100644
index 0000000..2594818
--- /dev/null
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoderRegistry.java
@@ -0,0 +1,85 @@
+/*
+ * 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.idp.attribute.transcoding;
+
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
+import net.shibboleth.utilities.java.support.component.IdentifiedComponent;
+
+
+/**
+ * The transcoder registry provides access to "instructions" for converting between
+ * the {@link IdPAttribute} "neutral" representation within the IdP and protocol-specific
+ * forms such as SAML Attributes or OIDC claims.
+ */
+ at ThreadSafe
+public interface AttributeTranscoderRegistry extends IdentifiedComponent {
+
+ /** Property name for accessing the name of the {@link IdPAttribute} to decode into. */
+ @Nonnull @NotEmpty static final String PROP_ID = "id";
+
+ /** Property name for accessing {@link AttributeTranscoder} object to use. */
+ @Nonnull @NotEmpty static final String PROP_TRANSCODER = "transcoder";
+
+ /** Property name for identifying an {@link AttributeTranscoder} class to build. */
+ @Nonnull @NotEmpty static final String PROP_TRANSCODER_CLASS = "transcoder_class";
+
+ /** Property name for accessing an activation condition object to apply. */
+ @Nonnull @NotEmpty static final String PROP_CONDITION = "activationCondition";
+
+ /** Property name for accessing relying parties to wrap an activation condition around. */
+ @Nonnull @NotEmpty static final String PROP_RELYINGPARTIES = "relyingParties";
+
+ /**
+ * Obtains a set of instructions for encoding an input {@link IdPAttribute} into a target type.
+ *
+ * <p>The principal property useful to a caller is {@link #PROP_TRANSCODER} to obtain an instance
+ * of the appropriate {@link AttributeTranscoder} to call, passing in the properties to drive that
+ * call.</p>
+ *
+ * @param from the input object to encode
+ * @param to class of object being encoded
+ *
+ * @return a collection of {@link TranscodingRule} objects, possibly empty
+ */
+ @Nonnull @NonnullElements @Unmodifiable
+ Collection<TranscodingRule> getTranscodingRules(@Nonnull final IdPAttribute from, @Nonnull final Class<?> to);
+
+ /**
+ * Obtains a set of instructions for decoding an input object into an {@link IdPAttribute}.
+ *
+ * <p>The principal property useful to a caller is {@link #PROP_TRANSCODER} to obtain an instance
+ * of the appropriate {@link AttributeTranscoder} to call, passing in the properties to drive that
+ * call.</p>
+ *
+ * @param <T> the type of object to decode
+ * @param from object to decode
+ *
+ * @return a collection of {@link TranscodingRule} objects, possibly empty
+ */
+ @Nonnull @NonnullElements @Unmodifiable <T> Collection<TranscodingRule> getTranscodingRules(
+ @Nonnull final T from);
+
+}
\ No newline at end of file
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscoderSupport.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscoderSupport.java
new file mode 100644
index 0000000..e9f8ac6
--- /dev/null
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscoderSupport.java
@@ -0,0 +1,55 @@
+/*
+ * 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.idp.attribute.transcoding;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.logic.ConstraintViolationException;
+
+/**
+ * Support functions for working with {@link AttributeTranscoder} framework.
+ */
+public final class TranscoderSupport {
+
+ /** Constructor. */
+ private TranscoderSupport() {
+
+ }
+
+ /**
+ * Pull an {@link AttributeTranscoder} object out of the rule provided.
+ *
+ * @param <T> type of supported target object
+ * @param rule transcoding rule
+ *
+ * @return an {@link AttributeTranscoder}
+ *
+ * @throws ConstraintViolationException if a transcoder cannot be obtained
+ */
+ @Nonnull public static <T> AttributeTranscoder<T> getTranscoder(@Nonnull final TranscodingRule rule)
+ throws ConstraintViolationException {
+ Constraint.isNotNull(rule, "Transcoding rule cannot be null");
+
+ final AttributeTranscoder<T> transcoder =
+ rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER, AttributeTranscoder.class);
+ Constraint.isNotNull(transcoder, "AttributeTranscoder not found in properties");
+ return transcoder;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscodingRule.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscodingRule.java
new file mode 100644
index 0000000..89bcf88
--- /dev/null
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscodingRule.java
@@ -0,0 +1,160 @@
+/*
+ * 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.idp.attribute.transcoding;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.springframework.core.io.Resource;
+
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.Live;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+
+/**
+ * Wrapper around a {@link Map} representing a rule for transcoding, used to
+ * detect and load the rules at runtime from a Spring context.
+ */
+public class TranscodingRule {
+
+ /** Underlying map containing the rule. */
+ @Nonnull @NonnullElements private final Map<String,Object> rule;
+
+ /**
+ * Constructor.
+ *
+ * @param map a map containing the rule
+ *
+ * <p>The rule MUST contain at least:</p>
+ * <ul>
+ * <li>
+ * {@link AttributeTranscoderRegistry#PROP_ID} - internal attribute ID to map to/from
+ * </li>
+ * <li>
+ * {@link AttributeTranscoderRegistry#PROP_TRANSCODER} - {@link AttributeTranscoder} instance supporting the type
+ * </li>
+ * </ul>
+ */
+ public TranscodingRule(@Nonnull @NonnullElements @ParameterName(name="map") final Map<String,Object> map) {
+ rule = new HashMap<>(map);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param properties a property set to initialize the map
+ *
+ * <p>The rule MUST contain at least:</p>
+ * <ul>
+ * <li>
+ * {@link AttributeTranscoderRegistry#PROP_ID} - internal attribute ID to map to/from
+ * </li>
+ * <li>
+ * {@link AttributeTranscoderRegistry#PROP_TRANSCODER} - {@link AttributeTranscoder} class name
+ * </li>
+ * </ul>
+ */
+ public TranscodingRule(@Nonnull @NonnullElements @ParameterName(name="properties") final Properties properties) {
+ rule = new HashMap<>(properties.size());
+ properties.forEach(
+ (k,v) -> {
+ if (k instanceof String && v != null) {
+ rule.put((String) k, v);
+ }
+ });
+ }
+
+ /**
+ * Access the underlying mapping rule.
+ *
+ * @return the map representing the rule
+ */
+ @Nonnull @NonnullElements @Live public Map<String,Object> getMap() {
+ return rule;
+ }
+
+ /**
+ * Get the value of a property key in the rule.
+ *
+ * @param <T> type of property value
+ * @param key key of property
+ * @param type class type of property
+ *
+ * @return the mapped value, or null
+ */
+ @Nullable public <T> T get(@Nonnull @NotEmpty final String key, @Nonnull final Class<T> type) {
+ final Object value = rule.get(key);
+ if (type.isInstance(value)) {
+ return (T) value;
+ } else if (type == Boolean.class && value instanceof String) {
+ return (T) Boolean.valueOf((String) value);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the value of a property key in the rule or a default value if no property exists.
+ *
+ * @param <T> type of property value
+ * @param key key of property
+ * @param type class type of property
+ * @param defValue default value
+ *
+ * @return the mapped value, or the default
+ */
+ @Nullable public <T> T getOrDefault(@Nonnull @NotEmpty final String key, @Nonnull final Class<T> type,
+ @Nullable final T defValue) {
+
+ final T value = get(key, type);
+ if (value != null) {
+ return value;
+ } else {
+ return defValue;
+ }
+ }
+
+ /**
+ * Build a new rule from a property set resource.
+ *
+ * @param resource a property set to initialize the map
+ *
+ * @return the new rule
+ *
+ * @throws IOException if an error occurs
+ */
+ @Nonnull public static TranscodingRule fromResource(
+ @Nonnull @ParameterName(name="resource") final Resource resource) throws IOException {
+
+ final Properties props = new Properties();
+
+ try (final InputStream is = resource.getInputStream()) {
+ props.load(is);
+ }
+
+ return new TranscodingRule(props);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/package-info.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/package-info.java
similarity index 85%
rename from idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/package-info.java
rename to idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/package-info.java
index 748f560..ca23131 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/package-info.java
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/package-info.java
@@ -16,6 +16,7 @@
*/
/**
- * Classes to do with the reverse mapping of SAML2 attributes into IdP Attributes.
+ * APIs for transcoding of attributes.
*/
-package net.shibboleth.idp.saml.attribute.mapping.impl;
\ No newline at end of file
+
+package net.shibboleth.idp.attribute.transcoding;
\ No newline at end of file
diff --git a/idp-attribute-api/src/test/java/net/shibboleth/idp/attribute/AttributeTest.java b/idp-attribute-api/src/test/java/net/shibboleth/idp/attribute/AttributeTest.java
index 8d82637..bf3187e 100644
--- a/idp-attribute-api/src/test/java/net/shibboleth/idp/attribute/AttributeTest.java
+++ b/idp-attribute-api/src/test/java/net/shibboleth/idp/attribute/AttributeTest.java
@@ -18,15 +18,11 @@
package net.shibboleth.idp.attribute;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Set;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -48,9 +44,6 @@ public class AttributeTest {
Assert.assertNotNull(attrib.getDisplayNames());
Assert.assertTrue(attrib.getDisplayNames().isEmpty());
- Assert.assertNotNull(attrib.getEncoders());
- Assert.assertTrue(attrib.getEncoders().isEmpty());
-
Assert.assertNotNull(attrib.getValues());
Assert.assertTrue(attrib.getValues().isEmpty());
@@ -316,62 +309,6 @@ public class AttributeTest {
Assert.assertTrue(attrib.getValues().contains(value2));
}
- /** Tests that values are properly added and modified. */
- @Test public void encoders() {
- AttributeEncoder<String> enc1 = new MockEncoder<>();
- AttributeEncoder<String> enc2 = new MockEncoder<>();
-
- IdPAttribute attrib = new IdPAttribute("foo");
- Assert.assertTrue(attrib.getEncoders().isEmpty());
- attrib.setEncoders(null);
- Assert.assertTrue(attrib.getEncoders().isEmpty());
- Collection collection = Arrays.asList((AttributeEncoder)null);
- attrib.setEncoders(collection);
- Assert.assertTrue(attrib.getEncoders().isEmpty());
-
- Set<AttributeEncoder<?>> attribEncoders = new HashSet<>();
-
- // test adding one entry
- Assert.assertTrue(attribEncoders.add(enc1));
- attrib.setEncoders(attribEncoders);
- Assert.assertFalse(attrib.getEncoders().isEmpty());
- Assert.assertEquals(attrib.getEncoders().size(), 1);
- Assert.assertTrue(attrib.getEncoders().contains(enc1));
-
- // test adding another entry
- Assert.assertTrue(attribEncoders.add(enc2));
- attrib.setEncoders(attribEncoders);
- Assert.assertFalse(attrib.getEncoders().isEmpty());
- Assert.assertEquals(attrib.getEncoders().size(), 2);
- Assert.assertTrue(attrib.getEncoders().contains(enc1));
- Assert.assertTrue(attrib.getEncoders().contains(enc2));
-
- // test adding null
-
- attribEncoders.add(null);
- attrib.setEncoders(attribEncoders);
- Assert.assertFalse(attrib.getEncoders().isEmpty());
- Assert.assertEquals(attrib.getEncoders().size(), 2);
- Assert.assertTrue(attrib.getEncoders().contains(enc1));
- Assert.assertTrue(attrib.getEncoders().contains(enc2));
-
- // test adding an existing Encoder
- Assert.assertFalse(attribEncoders.add(enc2));
- attrib.setEncoders(attribEncoders);
- Assert.assertFalse(attrib.getEncoders().isEmpty());
- Assert.assertEquals(attrib.getEncoders().size(), 2);
- Assert.assertTrue(attrib.getEncoders().contains(enc1));
- Assert.assertTrue(attrib.getEncoders().contains(enc2));
-
- try {
- attrib.getEncoders().add(null);
- Assert.fail();
- } catch (UnsupportedOperationException e) {
- // OK
- }
-
- }
-
@SuppressWarnings("unlikely-arg-type")
@Test public void cloneToString() {
IdPAttribute attrib = new IdPAttribute("foo");
diff --git a/idp-attribute-api/src/test/java/net/shibboleth/idp/attribute/MockEncoder.java b/idp-attribute-api/src/test/java/net/shibboleth/idp/attribute/MockEncoder.java
deleted file mode 100644
index 69d089f..0000000
--- a/idp-attribute-api/src/test/java/net/shibboleth/idp/attribute/MockEncoder.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.idp.attribute;
-
-import java.util.function.Predicate;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-
-import com.google.common.base.Predicates;
-
-/**
- * Mock implementation of {@link AttributeEncoder}.
- *
- * @param <ValueType> type of value produced by this encoder
- */
-public class MockEncoder<ValueType> implements AttributeEncoder<ValueType> {
-
- /** Static protocol string for this encoder. */
- private String proto;
-
- /** Static encoded attribute value for this encoder. */
- private ValueType encodedValue;
-
- /** Constructor. */
- public MockEncoder() {
-
- }
-
- /**
- * Constructor.
- *
- * @param protocol static value to bereturned from {@link #getProtocol()}
- * @param encodedAttributeValue static value to be returned from {@link #encode(IdPAttribute)}
- */
- public MockEncoder(String protocol, ValueType encodedAttributeValue) {
- proto = protocol;
- encodedValue = encodedAttributeValue;
- }
-
- /** {@inheritDoc} */
- public String getProtocol() {
- return proto;
- }
-
- /** {@inheritDoc} */
- public ValueType encode(IdPAttribute attribute) throws AttributeEncodingException {
- return encodedValue;
- }
-
- /** {@inheritDoc} */
- public Predicate<ProfileRequestContext> getActivationCondition() {
- return Predicates.alwaysTrue();
- }
-
-}
\ No newline at end of file
diff --git a/idp-attribute-filter-api/.project b/idp-attribute-filter-api/.project
index a33e638..4b2ce71 100644
--- a/idp-attribute-filter-api/.project
+++ b/idp-attribute-filter-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-attribute-filter-impl/.project b/idp-attribute-filter-impl/.project
index 0815e7a..70a90af 100644
--- a/idp-attribute-filter-impl/.project
+++ b/idp-attribute-filter-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/AttributeInMetadataMatcher.java b/idp-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/AttributeInMetadataMatcher.java
index 584974f..eccc8cc 100644
--- a/idp-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/AttributeInMetadataMatcher.java
+++ b/idp-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/AttributeInMetadataMatcher.java
@@ -18,6 +18,7 @@
package net.shibboleth.idp.attribute.filter.matcher.saml.impl;
import java.time.Instant;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -26,15 +27,15 @@ import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
import net.shibboleth.idp.attribute.StringAttributeValue;
import net.shibboleth.idp.attribute.filter.Matcher;
import net.shibboleth.idp.attribute.filter.context.AttributeFilterContext;
-import net.shibboleth.idp.saml.attribute.encoding.SAML1AttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.SAML2AttributeEncoder;
+import net.shibboleth.idp.saml.attribute.transcoding.AttributesMapContainer;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
@@ -56,7 +57,10 @@ import org.opensaml.saml.saml2.metadata.RequestedAttribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
/**
@@ -75,13 +79,13 @@ public class AttributeInMetadataMatcher extends AbstractIdentifiableInitializabl
private boolean matchIfMetadataSilent;
/** The SAML Attribute Name to look for in the metadata. */
- private String attributeName;
+ @Nullable @NotEmpty private String attributeName;
/** The SAML Attribute NameFormat to look for in the metadata. */
- private String attributeNameFormat;
+ @Nullable @NotEmpty private String attributeNameFormat;
/** The String used to prefix log message. */
- private String logPrefix;
+ @Nullable @NotEmpty private String logPrefix;
/**
* Gets whether optionally requested attributes should be matched.
@@ -125,7 +129,7 @@ public class AttributeInMetadataMatcher extends AbstractIdentifiableInitializabl
*
* @return the Name to look for
*/
- @Nullable public String getAttributeName() {
+ @Nullable @NotEmpty public String getAttributeName() {
return attributeName;
}
@@ -137,7 +141,7 @@ public class AttributeInMetadataMatcher extends AbstractIdentifiableInitializabl
*
* @param name the Name to look for
*/
- public void setAttributeName(@Nullable final String name) {
+ public void setAttributeName(@Nullable @NotEmpty final String name) {
attributeName = StringSupport.trimOrNull(name);
}
@@ -147,7 +151,7 @@ public class AttributeInMetadataMatcher extends AbstractIdentifiableInitializabl
*
* @return the Name to look for
*/
- @Nullable public String getAttributeNameFormat() {
+ @Nullable @NotEmpty public String getAttributeNameFormat() {
return attributeNameFormat;
}
@@ -159,14 +163,14 @@ public class AttributeInMetadataMatcher extends AbstractIdentifiableInitializabl
*
* @param format the NameFormat to look for
*/
- public void setAttributeNameFormat(@Nullable final String format) {
+ public void setAttributeNameFormat(@Nullable @NotEmpty final String format) {
attributeNameFormat = StringSupport.trimOrNull(format);
if (attributeNameFormat != null && Attribute.UNSPECIFIED.equals(attributeNameFormat)) {
attributeNameFormat = null;
}
}
-// Checkstyle: CyclomaticComplexity OFF
+// Checkstyle: CyclomaticComplexity|ReturnCount|MethodLength OFF
/** {@inheritDoc} */
@Override @Nonnull public Set<IdPAttributeValue<?>> getMatchingValues(@Nonnull final IdPAttribute attribute,
@Nonnull final AttributeFilterContext filterContext) {
@@ -186,42 +190,79 @@ public class AttributeInMetadataMatcher extends AbstractIdentifiableInitializabl
}
}
- RequestedAttribute requestedAttribute = null;
if (attributeName != null) {
// Look for a RequestedAttribute explicitly identified by config.
- log.debug("Looking for RequestedAttribute {} (NameFormat {}) in descriptor", attributeName,
+ log.debug("Looking for RequestedAttribute {} (NameFormat {}) in metadata", attributeName,
attributeNameFormat);
- requestedAttribute = findInMetadata(service, attributeName, attributeNameFormat);
- } else {
- final Set<AttributeEncoder<?>> encoders = attribute.getEncoders();
- for (final AttributeEncoder<?> encoder : encoders) {
- requestedAttribute = findInMetadata(service, encoder);
- if (requestedAttribute != null) {
- break;
- }
- }
- }
-
- final String attributeToLog = attributeName != null ? attributeName : attribute.getId();
+ final RequestedAttribute requestedAttribute = findInMetadata(service, attributeName, attributeNameFormat);
+ final String attributeToLog = attributeName != null ? attributeName : attribute.getId();
- if (null == requestedAttribute) {
- log.debug("{} Attribute {} not found in metadata", getLogPrefix(), attributeToLog);
- return Collections.emptySet();
- }
-
- if (requestedAttribute != null) {
+ if (null == requestedAttribute) {
+ log.debug("{} Attribute {} not found in metadata", getLogPrefix(), attributeToLog);
+ return Collections.emptySet();
+ }
+
if (onlyIfRequired && !requestedAttribute.isRequired()) {
log.debug("{} Attribute {} found in metadata, but was not required, values not matched",
getLogPrefix(), attributeToLog);
return Collections.emptySet();
}
+
+ final Set<IdPAttributeValue<?>> values = new HashSet<>();
+ values.addAll(filterValues(attributeToLog, attribute, requestedAttribute.getAttributeValues()));
+ return values;
+ } else {
+ // Utilize pre-mapped approach.
+ final List<AttributesMapContainer> containerList =
+ service.getObjectMetadata().get(AttributesMapContainer.class);
+ if (null == containerList || containerList.isEmpty() || containerList.get(0).get() == null ||
+ containerList.get(0).get().isEmpty()) {
+ log.debug("{} No decoded attributes found when filtering", getLogPrefix());
+ if (matchIfMetadataSilent) {
+ // TODO: not sure what the right answer is here
+ log.debug("{} The peer's metadata did not contain requested attribute information"
+ + ", returning all the input values", getLogPrefix());
+ return ImmutableSet.copyOf(attribute.getValues());
+ } else {
+ log.debug("{} The peer's metadata did not contain requested attribute information"
+ + ", returning no values", getLogPrefix());
+ return Collections.emptySet();
+ }
+ }
+ if (containerList.size() > 1) {
+ log.error("{} More than one set of mapped attributes found when filtering, this shouldn't ever happen",
+ getLogPrefix());
+ }
+
+ final Multimap<String,? extends IdPAttribute> requestedAttributes = containerList.get(0).get();
+
+ final Collection<? extends IdPAttribute> requestedAttributeList =
+ requestedAttributes.get(attribute.getId());
+ if (null == requestedAttributeList) {
+ log.debug("{} Decoded attribute {} not found in metadata", getLogPrefix(), attribute.getId());
+ return Collections.emptySet();
+ }
+
+ final Set<IdPAttributeValue<?>> values = new HashSet<>();
+
+ for (final IdPAttribute requestedAttribute
+ : Collections2.filter(requestedAttributeList, Predicates.notNull())) {
+
+ if (requestedAttribute instanceof IdPRequestedAttribute
+ && !((IdPRequestedAttribute) requestedAttribute).getIsRequired() && onlyIfRequired) {
+ log.debug("{} Decoded attribute {} found in metadata, but not required, values not matched",
+ getLogPrefix(), attribute.getId());
+ continue;
+ }
+
+ values.addAll(filterValues(attribute, requestedAttribute.getValues()));
+ }
+
+ return values;
}
-
- final Set<IdPAttributeValue<?>> values = new HashSet<>();
- values.addAll(filterValues(attributeToLog, attribute, requestedAttribute.getAttributeValues()));
- return values;
+
}
-// Checkstyle: CyclomaticComplexity ON
+// Checkstyle: CyclomaticComplexity|ReturnCount|MethodLength ON
/**
* Get the appropriate {@link AttributeConsumingService}.
@@ -245,30 +286,6 @@ public class AttributeInMetadataMatcher extends AbstractIdentifiableInitializabl
}
/**
- * Locates a {@link RequestedAttribute} object in metadata that matches the eventual "to be encoded" name
- * represented by the encoder.
- *
- * @param service the metadata descriptor to search
- * @param encoder the attribute encoder to base the search on
- *
- * @return a matching RequestedAttribute, or null
- */
- @Nullable private RequestedAttribute findInMetadata(@Nonnull final AttributeConsumingService service,
- @Nonnull final AttributeEncoder encoder) {
- String name = null;
- String qualifier = null;
- if (encoder instanceof SAML2AttributeEncoder) {
- name = ((SAML2AttributeEncoder) encoder).getName();
- qualifier = ((SAML2AttributeEncoder) encoder).getNameFormat();
- } else if (encoder instanceof SAML1AttributeEncoder) {
- name = ((SAML1AttributeEncoder) encoder).getName();
- qualifier = ((SAML1AttributeEncoder) encoder).getNamespace();
- }
-
- return findInMetadata(service, name, qualifier);
- }
-
- /**
* Locates a RequestedAttribute object in metadata that matches a specific Attribute Name
* and NameFormat.
*
@@ -296,6 +313,34 @@ public class AttributeInMetadataMatcher extends AbstractIdentifiableInitializabl
/**
* Given an attribute and the requested values do the filtering.
*
+ * @param attribute the attribute
+ * @param requestedValues the values
+ * @return the result of the filter
+ */
+ @Nonnull private Set<IdPAttributeValue<?>> filterValues(@Nullable final IdPAttribute attribute,
+ @Nonnull @NonnullElements final List<IdPAttributeValue<?>> requestedValues) {
+
+ if (null == requestedValues || requestedValues.isEmpty()) {
+ log.debug("{} Attribute {} found in metadata and no values specified", getLogPrefix(), attribute.getId());
+ return ImmutableSet.copyOf(attribute.getValues());
+ }
+
+ final ImmutableSet.Builder<IdPAttributeValue<?>> builder = ImmutableSet.builder();
+
+ for (final IdPAttributeValue attributeValue : attribute.getValues()) {
+ if (requestedValues.contains(attributeValue)) {
+ builder.add(attributeValue);
+ }
+ }
+
+ final ImmutableSet<IdPAttributeValue<?>> result = builder.build();
+ log.debug("{} Values matched with metadata for Attribute {} : {}", getLogPrefix(), attribute.getId(), result);
+ return result;
+ }
+
+ /**
+ * Given an attribute and the requested values do the filtering.
+ *
* @param attributeToLog name of attribute to log
* @param attribute the attribute
* @param requestedValues the values
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
deleted file mode 100644
index 4109814..0000000
--- a/idp-attribute-filter-impl/src/main/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/MappedAttributeInMetadataMatcher.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * 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.idp.attribute.filter.matcher.saml.impl;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-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.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.saml.common.messaging.context.AttributeConsumingServiceContext;
-import org.opensaml.saml.common.messaging.context.SAMLMetadataContext;
-import org.opensaml.saml.common.messaging.context.navigate.AttributeConsumerServiceLookupFunction;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-
-/**
- * Matcher that checks whether an attribute is enumerated in an SP's metadata as a required or optional attribute.
- * Also supports simple value filtering.
- *
- * <p>This matcher compares attributes from the metadata that have been mapped into {@link IdPAttribute}s.</p>
- */
-public class MappedAttributeInMetadataMatcher extends AbstractIdentifiableInitializableComponent implements Matcher {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(MappedAttributeInMetadataMatcher.class);
-
- /** Whether optionally requested attributes should be matched. */
- private boolean onlyIfRequired = true;
-
- /** Whether to return a match if the metadata does not contain an ACS descriptor. */
- private boolean matchIfMetadataSilent;
-
- /** The String used to prefix log message. */
- private String logPrefix;
-
- /** The strategy to get the appropriate XMLObject from the context. */
- @Nonnull private Function<SAMLMetadataContext, ? extends XMLObject> objectStrategy;
-
- /** Constructor. */
- public MappedAttributeInMetadataMatcher() {
- objectStrategy = new AttributeConsumerServiceLookupFunction().compose(
- new ChildContextLookup<>(AttributeConsumingServiceContext.class));
- }
-
- /**
- * Gets whether optionally requested attributes should be matched.
- *
- * @return Whether optionally requested attributes should be matched.
- */
- public boolean getOnlyIfRequired() {
- return onlyIfRequired;
- }
-
- /**
- * Sets whether optionally requested attributes should be matched.
- *
- * @param flag whether optionally requested attributes should be matched
- */
- public void setOnlyIfRequired(final boolean flag) {
- onlyIfRequired = flag;
- }
-
- /**
- * Get the strategy to get the appropriate XMLObject from the context.
- *
- * @return Returns the strategy.
- */
- public Function<SAMLMetadataContext, ? extends XMLObject> getXMLObjectStrategy() {
- return objectStrategy;
- }
-
- /**
- * Set the strategy to get the appropriate XMLObject from the context.
- *
- * @param strategy what to set.
- */
- public void setObjectStrategy(@Nonnull final Function<SAMLMetadataContext, ? extends XMLObject> strategy) {
- objectStrategy = Constraint.isNotNull(strategy, "ObjectStrategy must be non null");
- }
-
- /**
- * Gets whether to matched if the metadata contains no AttributeConsumingService.
- *
- * @return whether to match if the metadata contains no AttributeConsumingService
- */
- public boolean getMatchIfMetadataSilent() {
- return matchIfMetadataSilent;
- }
-
- /**
- * Sets whether to match if the metadata contains no AttributeConsumingService.
- *
- * @param flag whether to match if the metadata contains no AttributeConsumingService
- */
- public void setMatchIfMetadataSilent(final boolean flag) {
- matchIfMetadataSilent = flag;
- }
-
- /**
- * Get the appropriate map of mapped attributes.
- *
- * @param filterContext the context for the operation
- * @return the map, or null.
- */
- @Nullable protected Multimap<String, ? extends IdPAttribute> getRequestedAttributes(
- @Nonnull final AttributeFilterContext filterContext) {
- final SAMLMetadataContext metadataContext = filterContext.getRequesterMetadataContext();
- if (null == metadataContext) {
- log.warn("{} No metadata context when filtering", getLogPrefix());
- return null;
- }
-
- final XMLObject xmlObject = getXMLObjectStrategy().apply(metadataContext);
- if (null == xmlObject) {
- log.warn("{} No RP XML Object found when filtering", getLogPrefix());
- return null;
- }
- final List<AttributesMapContainer> containerList =
- xmlObject.getObjectMetadata().get(AttributesMapContainer.class);
- if (null == containerList || containerList.isEmpty()) {
- log.debug("{} No mapped attributes found when filtering", getLogPrefix());
- return null;
- }
- if (containerList.size() > 1) {
- log.warn("{} More than one set of mapped attributes found when filtering, please report an error",
- getLogPrefix());
- }
- return containerList.get(0).get();
- }
-
- /** {@inheritDoc} */
- @Override @Nonnull public Set<IdPAttributeValue<?>> getMatchingValues(@Nonnull final IdPAttribute attribute,
- @Nonnull final AttributeFilterContext filterContext) {
-
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
- final Multimap<String, ? extends IdPAttribute> requestedAttributes = getRequestedAttributes(filterContext);
-
- if (null == requestedAttributes || requestedAttributes.isEmpty()) {
- if (matchIfMetadataSilent) {
- log.debug("{} The peer's metadata did not have appropriate requested attributes available"
- + ", returning all the input values", getLogPrefix());
- return ImmutableSet.copyOf(attribute.getValues());
- } else {
- log.debug("{} The peer's metadata did not have appropriate requested attributes available"
- + ", returning no values", getLogPrefix());
- return Collections.emptySet();
- }
- }
-
- final Collection<? extends IdPAttribute> requestedAttributeList = requestedAttributes.get(attribute.getId());
-
- if (null == requestedAttributeList) {
- log.debug("{} Attribute {} not found in metadata", getLogPrefix(), attribute.getId());
- return Collections.emptySet();
- }
-
- final Set<IdPAttributeValue<?>> values = new HashSet<>();
-
- for (final IdPAttribute requestedAttribute : requestedAttributeList) {
-
- if (null == requestedAttribute) {
- log.info("{} Attribute {} found in metadata but with no values that"
- + " could be decoded, values not matched", getLogPrefix(), attribute.getId());
- continue;
- }
-
- if (requestedAttribute instanceof IdPRequestedAttribute
- && !((IdPRequestedAttribute) requestedAttribute).getIsRequired() && onlyIfRequired) {
- log.debug("{} Attribute {} found in metadata, but was not required, values not matched",
- getLogPrefix(), attribute.getId());
- continue;
- }
-
- values.addAll(filterValues(attribute, requestedAttribute.getValues()));
- }
- return values;
- }
-
- /**
- * Given an attribute and the requested values do the filtering.
- *
- * @param attribute the attribute
- * @param requestedValues the values
- * @return the result of the filter
- */
- @Nonnull private Set<IdPAttributeValue<?>> filterValues(@Nullable final IdPAttribute attribute,
- @Nonnull @NonnullElements final List<IdPAttributeValue<?>> requestedValues) {
-
- if (null == requestedValues || requestedValues.isEmpty()) {
- log.debug("{} Attribute {} found in metadata and no values specified", getLogPrefix(), attribute.getId());
- return ImmutableSet.copyOf(attribute.getValues());
- }
-
- final ImmutableSet.Builder<IdPAttributeValue<?>> builder = ImmutableSet.builder();
-
- for (final IdPAttributeValue attributeValue : attribute.getValues()) {
- if (requestedValues.contains(attributeValue)) {
- builder.add(attributeValue);
- }
- }
-
- final ImmutableSet<IdPAttributeValue<?>> result = builder.build();
- log.debug("{} Values matched with metadata for Attribute {} : {}", getLogPrefix(), attribute.getId(), result);
- return result;
- }
-
- /**
- * return a string which is to be prepended to all log messages.
- *
- * @return "Attribute Filter '<filterID>' :"
- */
- @Nonnull protected String getLogPrefix() {
- // local cache of cached entry to allow unsynchronised clearing.
- String prefix = logPrefix;
- if (null == prefix) {
- final StringBuilder builder = new StringBuilder("Attribute Filter '").append(getId()).append("':");
- prefix = builder.toString();
- if (null == logPrefix) {
- logPrefix = prefix;
- }
- }
- return prefix;
- }
-
-}
\ No newline at end of file
diff --git a/idp-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/AttributeInMetadataMatcherTest.java b/idp-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/AttributeInMetadataMatcherTest.java
index d9405d4..50c5e90 100644
--- a/idp-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/AttributeInMetadataMatcherTest.java
+++ b/idp-attribute-filter-impl/src/test/java/net/shibboleth/idp/attribute/filter/matcher/saml/impl/AttributeInMetadataMatcherTest.java
@@ -17,10 +17,7 @@
package net.shibboleth.idp.attribute.filter.matcher.saml.impl;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.*;
import java.util.Arrays;
import java.util.Collection;
@@ -43,12 +40,10 @@ import org.opensaml.saml.saml2.metadata.RequestedAttribute;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.IdPAttributeValue;
import net.shibboleth.idp.attribute.filter.context.AttributeFilterContext;
import net.shibboleth.idp.attribute.filter.matcher.impl.DataSources;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2StringAttributeEncoder;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
/**
@@ -73,12 +68,6 @@ public class AttributeInMetadataMatcherTest extends OpenSAMLInitBaseTestCase {
private IdPAttribute makeAttribute(String id, List<IdPAttributeValue<?>> values) {
final IdPAttribute attr = new IdPAttribute(id);
attr.setValues(values);
-
- final SAML2StringAttributeEncoder encoder = new SAML2StringAttributeEncoder();
- encoder.setName(id);
- encoder.setNameFormat(Attribute.BASIC);
-
- attr.setEncoders(Collections.<AttributeEncoder<?>>singleton(encoder));
return attr;
}
@@ -155,7 +144,7 @@ public class AttributeInMetadataMatcherTest extends OpenSAMLInitBaseTestCase {
final IdPAttribute attr =
makeAttribute("attr", Arrays.asList(DataSources.STRING_VALUE, DataSources.NON_MATCH_STRING_VALUE));
- final AttributeInMetadataMatcher matcher = makeMatcher("test", true, false, null, null);
+ final AttributeInMetadataMatcher matcher = makeMatcher("test", true, false, "wrongAttr", Attribute.URI_REFERENCE);
Set<IdPAttributeValue<?>> result = matcher.getMatchingValues(attr, makeContext(null));
assertEquals(result.size(), 2);
@@ -197,13 +186,14 @@ public class AttributeInMetadataMatcherTest extends OpenSAMLInitBaseTestCase {
req.setNameFormat(Attribute.BASIC);
final AttributeFilterContext context = makeContext(req);
- Set<IdPAttributeValue<?>> result = makeMatcher("test", false, false, null, null).getMatchingValues(attr, context);
+ Set<IdPAttributeValue<?>> result =
+ makeMatcher("test", false, false, "attr", Attribute.BASIC).getMatchingValues(attr, context);
assertEquals(result.size(), 2);
assertTrue(result.contains(DataSources.STRING_VALUE));
assertTrue(result.contains(DataSources.NON_MATCH_STRING_VALUE));
- result = makeMatcher("test", false, true, null, null).getMatchingValues(attr, context);
+ result = makeMatcher("test", false, true, "attr", Attribute.BASIC).getMatchingValues(attr, context);
assertTrue(result.isEmpty());
}
@@ -222,7 +212,8 @@ public class AttributeInMetadataMatcherTest extends OpenSAMLInitBaseTestCase {
final AttributeFilterContext context = makeContext(req);
- Set<IdPAttributeValue<?>> result = makeMatcher("test", false, true, null, null).getMatchingValues(attr, context);
+ final Set<IdPAttributeValue<?>> result =
+ makeMatcher("test", false, true, "attr", Attribute.BASIC).getMatchingValues(attr, context);
assertEquals(result.size(), 1);
assertTrue(result.contains(DataSources.STRING_VALUE));
}
@@ -249,7 +240,8 @@ public class AttributeInMetadataMatcherTest extends OpenSAMLInitBaseTestCase {
setRequestedAttributesInContext(context, Collections.singletonList(req));
- Set<IdPAttributeValue<?>> result = makeMatcher("test", false, true, null, null).getMatchingValues(attr, context);
+ final Set<IdPAttributeValue<?>> result =
+ makeMatcher("test", false, true, "attr", Attribute.BASIC).getMatchingValues(attr, context);
assertEquals(result.size(), 2);
assertTrue(result.contains(DataSources.STRING_VALUE));
assertTrue(result.contains(DataSources.NON_MATCH_STRING_VALUE));
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..8063fa1 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,11 +44,11 @@ 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;
/**
- * Tests for {@link MappedAttributeInMetadataMatcher}.
+ * Tests for {@link AttributeInMetadataMatcher} using decoded attributes.
*/
public class MappedAttributeInMetadataMatcherTest extends OpenSAMLInitBaseTestCase {
@@ -66,9 +66,9 @@ public class MappedAttributeInMetadataMatcherTest extends OpenSAMLInitBaseTestCa
return attr;
}
- private MappedAttributeInMetadataMatcher makeMatcher(String id, boolean matchIfMetadataSilent, boolean onlyIfRequired)
+ private AttributeInMetadataMatcher makeMatcher(String id, boolean matchIfMetadataSilent, boolean onlyIfRequired)
throws ComponentInitializationException {
- MappedAttributeInMetadataMatcher matcher = new MappedAttributeInMetadataMatcher();
+ AttributeInMetadataMatcher matcher = new AttributeInMetadataMatcher();
matcher.setMatchIfMetadataSilent(matchIfMetadataSilent);
matcher.setOnlyIfRequired(onlyIfRequired);
matcher.setId(id);
@@ -109,7 +109,7 @@ public class MappedAttributeInMetadataMatcherTest extends OpenSAMLInitBaseTestCa
}
@Test public void getters() throws ComponentInitializationException {
- MappedAttributeInMetadataMatcher matcher = makeMatcher("test", true, true);
+ AttributeInMetadataMatcher matcher = makeMatcher("test", true, true);
assertTrue(matcher.getMatchIfMetadataSilent());
assertTrue(matcher.getOnlyIfRequired());
@@ -139,7 +139,7 @@ public class MappedAttributeInMetadataMatcherTest extends OpenSAMLInitBaseTestCa
final IdPAttribute attr =
makeAttribute("attr", Arrays.asList(DataSources.STRING_VALUE, DataSources.NON_MATCH_STRING_VALUE));
- final MappedAttributeInMetadataMatcher matcher = makeMatcher("test", true, true);
+ final AttributeInMetadataMatcher matcher = makeMatcher("test", true, true);
Set<IdPAttributeValue<?>> result = matcher.getMatchingValues(attr, makeContext(null));
assertEquals(result.size(), 2);
diff --git a/idp-attribute-filter-spring/.project b/idp-attribute-filter-spring/.project
index 142d855..200fb1b 100644
--- a/idp-attribute-filter-spring/.project
+++ b/idp-attribute-filter-spring/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-attribute-filter-spring/src/main/java/net/shibboleth/idp/attribute/filter/spring/saml/impl/MappedAttributeInMetadataRuleParser.java b/idp-attribute-filter-spring/src/main/java/net/shibboleth/idp/attribute/filter/spring/saml/impl/MappedAttributeInMetadataRuleParser.java
index a73fe2f..d728030 100644
--- a/idp-attribute-filter-spring/src/main/java/net/shibboleth/idp/attribute/filter/spring/saml/impl/MappedAttributeInMetadataRuleParser.java
+++ b/idp-attribute-filter-spring/src/main/java/net/shibboleth/idp/attribute/filter/spring/saml/impl/MappedAttributeInMetadataRuleParser.java
@@ -20,9 +20,11 @@ package net.shibboleth.idp.attribute.filter.spring.saml.impl;
import javax.annotation.Nonnull;
import javax.xml.namespace.QName;
-import net.shibboleth.idp.attribute.filter.matcher.saml.impl.MappedAttributeInMetadataMatcher;
+import net.shibboleth.idp.attribute.filter.matcher.saml.impl.AttributeInMetadataMatcher;
import net.shibboleth.idp.attribute.filter.spring.BaseFilterParser;
import net.shibboleth.idp.attribute.filter.spring.matcher.BaseAttributeValueMatcherParser;
+import net.shibboleth.utilities.java.support.primitive.DeprecationSupport;
+import net.shibboleth.utilities.java.support.primitive.DeprecationSupport.ObjectType;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -39,13 +41,19 @@ public class MappedAttributeInMetadataRuleParser extends BaseAttributeValueMatch
"MappedAttributeInMetadata");
/** {@inheritDoc} */
- @Override @Nonnull protected Class<MappedAttributeInMetadataMatcher> getNativeBeanClass() {
- return MappedAttributeInMetadataMatcher.class;
+ @Override @Nonnull protected Class<AttributeInMetadataMatcher> getNativeBeanClass() {
+ return AttributeInMetadataMatcher.class;
}
/** {@inheritDoc} */
@Override protected void doNativeParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
@Nonnull final BeanDefinitionBuilder builder) {
+
+ // V4 deprecation
+ DeprecationSupport.warn(ObjectType.XSITYPE, SCHEMA_TYPE.toString(),
+ parserContext.getReaderContext().getResource().getDescription(),
+ AttributeInMetadataRuleParser.SCHEMA_TYPE.toString());
+
super.doParse(config, builder);
if (config.hasAttributeNS(null, "onlyIfRequired")) {
diff --git a/idp-attribute-filter-spring/src/test/java/net/shibboleth/idp/attribute/filter/spring/saml/MappedAttributeInMetadataRuleParserTest.java b/idp-attribute-filter-spring/src/test/java/net/shibboleth/idp/attribute/filter/spring/saml/MappedAttributeInMetadataRuleParserTest.java
index a97cfac..e0d83f2 100644
--- a/idp-attribute-filter-spring/src/test/java/net/shibboleth/idp/attribute/filter/spring/saml/MappedAttributeInMetadataRuleParserTest.java
+++ b/idp-attribute-filter-spring/src/test/java/net/shibboleth/idp/attribute/filter/spring/saml/MappedAttributeInMetadataRuleParserTest.java
@@ -26,7 +26,7 @@ import net.shibboleth.ext.spring.context.FilesystemGenericApplicationContext;
import net.shibboleth.idp.attribute.filter.AttributeRule;
import net.shibboleth.idp.attribute.filter.PolicyFromMatcher;
import net.shibboleth.idp.attribute.filter.PolicyRequirementRule;
-import net.shibboleth.idp.attribute.filter.matcher.saml.impl.MappedAttributeInMetadataMatcher;
+import net.shibboleth.idp.attribute.filter.matcher.saml.impl.AttributeInMetadataMatcher;
import net.shibboleth.idp.attribute.filter.spring.BaseAttributeFilterParserTest;
import net.shibboleth.idp.attribute.filter.spring.saml.impl.MappedAttributeInMetadataRuleParser;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
@@ -43,14 +43,14 @@ public class MappedAttributeInMetadataRuleParserTest extends BaseAttributeFilte
final AttributeRule rule = getBean(MATCHER_PATH + "mappedInMetadata.xml", AttributeRule.class, context);
rule.initialize();
- MappedAttributeInMetadataMatcher matcher = (MappedAttributeInMetadataMatcher) rule.getMatcher();
+ AttributeInMetadataMatcher matcher = (AttributeInMetadataMatcher) rule.getMatcher();
assertTrue(matcher.getMatchIfMetadataSilent());
assertTrue(matcher.getOnlyIfRequired());
assertTrue(matcher.getId().endsWith(":PermitRule"));
final PolicyFromMatcher policyRule = (PolicyFromMatcher) getBean(PolicyRequirementRule.class, context);
- matcher = (MappedAttributeInMetadataMatcher) policyRule.getMatcher();
+ matcher = (AttributeInMetadataMatcher) policyRule.getMatcher();
assertTrue(matcher.getMatchIfMetadataSilent());
assertTrue(matcher.getOnlyIfRequired());
assertTrue(matcher.getId().endsWith(":PRR"));
diff --git a/idp-attribute-impl/.project b/idp-attribute-impl/.project
index 93b9a0c..3d22eed 100644
--- a/idp-attribute-impl/.project
+++ b/idp-attribute-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
diff --git a/idp-attribute-impl/pom.xml b/idp-attribute-impl/pom.xml
index a5329d5..1587f93 100644
--- a/idp-attribute-impl/pom.xml
+++ b/idp-attribute-impl/pom.xml
@@ -24,6 +24,12 @@
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>idp-profile-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
<!-- Provided Dependencies -->
<!-- Runtime Dependencies -->
diff --git a/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java b/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java
new file mode 100644
index 0000000..24262d3
--- /dev/null
+++ b/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java
@@ -0,0 +1,357 @@
+/*
+ * 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.idp.attribute.transcoding.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import net.shibboleth.ext.spring.service.AbstractServiceableComponent;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.profile.logic.RelyingPartyIdPredicate;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Multimap;
+
+/** Service implementation of the {@link AttributeTranscoderRegistry} interface. */
+ at ThreadSafe
+public class AttributeTranscoderRegistryImpl extends AbstractServiceableComponent<AttributeTranscoderRegistry>
+ implements AttributeTranscoderRegistry {
+
+ /** Bean name for identifying an {@link AttributeTranscoder} object to install. */
+ @Nonnull @NotEmpty static final String PROP_TRANSCODER_BEAN = "transcoder_bean";
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AttributeTranscoderRegistryImpl.class);
+
+ /** Registry of transcoding instructions for a given "name" and type of object. */
+ @Nonnull private final Map<String,Multimap<Class<?>,TranscodingRule>> transcodingRegistry;
+
+ /** Registry of naming functions for supported object types. */
+ @Nonnull private final Map<Class<?>,Function<?,String>> namingFunctionRegistry;
+
+ /** Constructor. */
+ public AttributeTranscoderRegistryImpl() {
+ transcodingRegistry = new HashMap<>();
+ namingFunctionRegistry = new HashMap<>();
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nonnull public AttributeTranscoderRegistry getComponent() {
+ return this;
+ }
+
+ /**
+ * Installs registry of naming functions mapped against the types of objects they support.
+ *
+ * @param registry map of types to naming functions
+ */
+ public void setNamingRegistry(@Nonnull @NonnullElements final Map<Class<?>,Function<?,String>> registry) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ namingFunctionRegistry.clear();
+
+ if (registry == null) {
+ return;
+ }
+
+ registry.forEach((k,v) -> {
+ if (k != null && v != null) {
+ namingFunctionRegistry.put(k, v);
+ }
+ });
+ }
+
+ /**
+ * Installs the transcoder mappings en masse.
+ *
+ * <p>Each map connects an {@link IdPAttribute} name to the rules for transcoding to/from it.</p>
+ *
+ * <p>The rules MUST contain at least:</p>
+ * <ul>
+ * <li>{@link #PROP_ID} - internal attribute ID to map to/from</li>
+ * <li>{@link #PROP_TRANSCODER} - an {@link AttributeTranscoder} instance supporting the type</li>
+ * </ul>
+ *
+ * Transcoders will generally require particular properties in their own right to function.
+ *
+ * @param mappings transcoding rulesets
+ */
+ public void setTranscoderRegistry(@Nonnull @NonnullElements final Collection<TranscodingRule> mappings) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ transcodingRegistry.clear();
+
+ if (mappings == null) {
+ return;
+ }
+
+ for (final TranscodingRule mapping : Collections2.filter(mappings, Predicates.notNull())) {
+
+ final String internalId = StringSupport.trimOrNull(mapping.get(PROP_ID, String.class));
+ if (internalId != null) {
+ final Predicate activationCondition = buildActivationCondition(mapping.getMap());
+ if (activationCondition != null) {
+ mapping.getMap().put(PROP_CONDITION, activationCondition);
+ } else {
+ mapping.getMap().remove(PROP_CONDITION);
+ }
+
+ final AttributeTranscoder transcoder = buildAttributeTranscoder(mapping);
+ if (transcoder != null) {
+ mapping.getMap().put(PROP_TRANSCODER, transcoder);
+ addMapping(internalId, transcoder, mapping.getMap());
+ } else {
+ log.warn("Unable to locate or build an AttributeTranscoder in rule for {}", internalId);
+ }
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Nonnull @NonnullElements @Unmodifiable public Collection<TranscodingRule> getTranscodingRules(
+ @Nonnull final IdPAttribute from, @Nonnull final Class<?> to) {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+ Constraint.isNotNull(from, "IdPAttribute cannot be null");
+ Constraint.isNotNull(to, "Target type cannot be null");
+
+ final Multimap<Class<?>,TranscodingRule> propertyCollections = transcodingRegistry.get(from.getId());
+ if (propertyCollections == null) {
+ return Collections.emptyList();
+ }
+
+ final Class<?> effectiveType = getEffectiveType(to);
+ if (effectiveType == null) {
+ log.warn("Unsupported object type: {}", to.getClass().getName());
+ return Collections.emptyList();
+ }
+
+ log.trace("Using rules for effective type {}", effectiveType.getName());
+
+ return ImmutableList.copyOf(propertyCollections.get(effectiveType));
+ }
+
+ /** {@inheritDoc} */
+ @Nonnull @NonnullElements @Unmodifiable public <T> Collection<TranscodingRule> getTranscodingRules(
+ @Nonnull final T from) {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+ Constraint.isNotNull(from, "Input object cannot be null");
+
+ final Class<?> effectiveType = getEffectiveType(from.getClass());
+ if (effectiveType == null) {
+ log.warn("Unsupported object type: {}", from.getClass().getName());
+ return Collections.emptyList();
+ }
+
+ log.trace("Using rules for effective type {}", effectiveType.getName());
+
+ final Function<?,String> namingFunction = namingFunctionRegistry.get(effectiveType);
+
+ // Don't know if we can work around this cast or not.
+ final String id = ((Function<? super T,String>) namingFunction).apply(from);
+ if (id != null) {
+ final Multimap<Class<?>,TranscodingRule> propertyCollections = transcodingRegistry.get(id);
+
+ return propertyCollections != null ? ImmutableList.copyOf(propertyCollections.get(effectiveType))
+ : Collections.emptyList();
+ } else {
+ log.warn("Object of type {} did not have a canonical name", from.getClass().getName());
+ }
+
+ return Collections.emptyList();
+ }
+
+ /**
+ * Get the appropriate {@link AttributeTranscoder} to use.
+ *
+ * @param rule transcoding rule
+ *
+ * @return a transcoder to install under the ruleset's {@link #PROP_TRANSCODER}
+ */
+ @Nullable private AttributeTranscoder buildAttributeTranscoder(@Nonnull final TranscodingRule rule) {
+
+ AttributeTranscoder transcoder = rule.get(PROP_TRANSCODER, AttributeTranscoder.class);
+ if (transcoder != null) {
+ return transcoder;
+ }
+
+ final String type = rule.get(PROP_TRANSCODER_CLASS, String.class);
+ if (type != null) {
+ try {
+ transcoder = (AttributeTranscoder) Class.forName(type).getDeclaredConstructor().newInstance();
+ transcoder.initialize();
+ return transcoder;
+ } catch (final InstantiationException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException | SecurityException
+ | ClassNotFoundException | ComponentInitializationException e) {
+ log.warn("Unable to create AttributeTranscoder of specified type {}", type, e);
+ return null;
+ }
+ }
+
+ final String id = rule.get(PROP_TRANSCODER_BEAN, String.class);
+ if (id != null) {
+ try {
+ transcoder = getApplicationContext().getBean(id, AttributeTranscoder.class);
+ transcoder.initialize();
+ return transcoder;
+ } catch (final Exception e) {
+ log.warn("Unable to locate AttributeTranscoder bean named {}", id, e);
+ return null;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Add a mapping between an {@link IdPAttribute} name and a set of transcoding rules.
+ *
+ * @param id name of the {@link IdPAttribute} to map to/from
+ * @param transcoder the transcoder for this rule
+ * @param ruleset transcoding rules
+ */
+ private void addMapping(@Nonnull @NotEmpty final String id, @Nonnull final AttributeTranscoder transcoder,
+ @Nonnull final Map<String,Object> ruleset) {
+
+
+ final TranscodingRule copy = new TranscodingRule(ruleset);
+
+ final Class<?> type = transcoder.getEncodedType();
+ final String targetName = transcoder.getEncodedName(copy);
+ if (targetName != null) {
+
+ log.debug("Attribute mapping: {} <-> {} via {}", id, targetName, transcoder.getClass().getSimpleName());
+
+ // Install mapping back to IdPAttribute's trimmed name.
+ copy.getMap().put(PROP_ID, id);
+
+ Multimap<Class<?>,TranscodingRule> rulesetsForIdPName = transcodingRegistry.get(id);
+ if (rulesetsForIdPName == null) {
+ rulesetsForIdPName = ArrayListMultimap.create();
+ transcodingRegistry.put(id, rulesetsForIdPName);
+ }
+
+ rulesetsForIdPName.put(type, copy);
+
+ Multimap<Class<?>,TranscodingRule> rulesetsForEncodedName = transcodingRegistry.get(targetName);
+ if (rulesetsForEncodedName == null) {
+ rulesetsForEncodedName = ArrayListMultimap.create();
+ transcodingRegistry.put(targetName, rulesetsForEncodedName);
+ }
+
+ rulesetsForEncodedName.put(type, copy);
+
+ } else {
+ log.warn("Transcoding rule for {} into type {} did not produce an encoded name", id, type.getName());
+ }
+ }
+
+ /**
+ * Build an appropriate {@link Predicate} to use as an activation condition within the ruleset.
+ *
+ * @param ruleset transcoding rules
+ *
+ * @return a predicate to install under the ruleset's {@link #PROP_CONDITION}
+ */
+ @Nullable private Predicate<ProfileRequestContext> buildActivationCondition(
+ @Nonnull final Map<String,Object> ruleset) {
+
+ Predicate effectiveCondition = null;
+
+ final Object baseCondition = ruleset.get(PROP_CONDITION);
+ if (baseCondition instanceof Predicate) {
+ effectiveCondition = (Predicate) baseCondition;
+ } else if (baseCondition != null) {
+ log.error("{} property did not contain a Predicate object, ignored", PROP_CONDITION);
+ }
+
+ Predicate relyingPartyCondition = null;
+
+ final Object relyingParties = ruleset.get(PROP_RELYINGPARTIES);
+ if (relyingParties instanceof Collection) {
+ relyingPartyCondition = new RelyingPartyIdPredicate((Collection<String>) relyingParties);
+ } else if (relyingParties instanceof String) {
+ final Collection<String> parsed = StringSupport.normalizeStringCollection(
+ StringSupport.stringToList((String) relyingParties, " "));
+ relyingPartyCondition = new RelyingPartyIdPredicate(parsed);
+ } else if (relyingParties != null) {
+ log.error("{} property did not contain a Collection or String, ignored", PROP_RELYINGPARTIES);
+ }
+
+ if (effectiveCondition == null) {
+ return relyingPartyCondition;
+ } else if (relyingPartyCondition != null) {
+ return effectiveCondition.and(relyingPartyCondition);
+ } else {
+ return effectiveCondition;
+ }
+ }
+
+ /**
+ * Convert an input type into the appropriate type (possibly itself) to use in looking up
+ * rules in the registry.
+ *
+ * @param inputType the type passed into the registry operation
+ *
+ * @return the appropriate type to use subsequently or null if not found
+ */
+ @Nullable private Class<?> getEffectiveType(@Nonnull final Class<?> inputType) {
+
+ // Check for explicit support.
+ if (namingFunctionRegistry.containsKey(inputType)) {
+ return inputType;
+ }
+
+ // Try each map entry for a match. Optimized around the assumption the
+ // map will be fairly small.
+ for (final Class<?> candidate : namingFunctionRegistry.keySet()) {
+ if (candidate.isAssignableFrom(inputType)) {
+ return candidate;
+ }
+ }
+
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/TranscodingRuleLoader.java b/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/TranscodingRuleLoader.java
new file mode 100644
index 0000000..844e40c
--- /dev/null
+++ b/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/TranscodingRuleLoader.java
@@ -0,0 +1,95 @@
+/*
+ * 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.idp.attribute.transcoding.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.FileSystemResource;
+
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+
+/**
+ * Wrapper around a {@link Map} representing a rule for transcoding, used to
+ * detect and load the rules at runtime from a Spring context.
+ */
+public class TranscodingRuleLoader {
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(TranscodingRuleLoader.class);
+
+ /** Rules loaded. */
+ private @Nonnull @NonnullElements final Collection<TranscodingRule> rules;
+
+ /**
+ * Load rules from all files found below a directory root.
+ *
+ * <p>Individual rules that fail to load will be skipped.</p>
+ *
+ * @param dir root to search
+ *
+ * @throws IOException if an error occurs
+ */
+ public TranscodingRuleLoader(@Nonnull @ParameterName(name="dir") final Path dir) throws IOException {
+
+ log.debug("Loading rules from directory ({})", dir);
+ rules = new ArrayList<>();
+
+ try (final DirectoryStream<Path> dirstream = Files.newDirectoryStream(dir)) {
+ for (final Path child : dirstream) {
+ final File file = child.toFile();
+ if (file.isDirectory()) {
+ try {
+ rules.addAll(new TranscodingRuleLoader(child).getRules());
+ } catch (final IOException e) {
+ log.error("Failed to load rules from directory ({})", file, e);
+ }
+ } else {
+ log.debug("Loading rule from property set in file ({})", file);
+ try {
+ rules.add(TranscodingRule.fromResource(new FileSystemResource(file)));
+ } catch (final IOException e) {
+ log.error("Failed to load rule from file ({})", file, e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the rules loaded by this object.
+ *
+ * @return collection of rules
+ */
+ @Nonnull @NonnullElements public Collection<TranscodingRule> getRules() {
+ return rules;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/package-info.java b/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/package-info.java
similarity index 85%
copy from idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/package-info.java
copy to idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/package-info.java
index 9b82bcc..b0a62a2 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/package-info.java
+++ b/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/package-info.java
@@ -16,8 +16,7 @@
*/
/**
- * Classes in this package are to do with the import of attributes
- * as an adjunct to filtering.
+ * Implementation classes for attribute transcoding.
*/
-package net.shibboleth.idp.saml.attribute.mapping;
\ No newline at end of file
+package net.shibboleth.idp.attribute.transcoding.impl;
\ No newline at end of file
diff --git a/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImplTest.java b/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImplTest.java
new file mode 100644
index 0000000..6bb0629
--- /dev/null
+++ b/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImplTest.java
@@ -0,0 +1,338 @@
+/*
+ * 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.idp.attribute.transcoding.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicates;
+
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.EmptyAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+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.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.utilities.java.support.collection.Pair;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+/**
+ * Test for {@link AttributeTranscoderRegistryImpl}.
+ */
+public class AttributeTranscoderRegistryImplTest {
+
+ private AttributeTranscoderRegistryImpl registry;
+
+ @BeforeClass public void setUp() throws ComponentInitializationException {
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ registry.setNamingRegistry(Collections.singletonMap(Pair.class, (Pair p) -> "{Pair}" + p.getFirst().toString()));
+
+ final PairTranscoder transcoder = new PairTranscoder();
+ transcoder.initialize();
+
+ final Map<String,Object> ruleset1 = new HashMap<>();
+ ruleset1.put(AttributeTranscoderRegistry.PROP_ID, "foo");
+ ruleset1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ ruleset1.put("name", "bar");
+
+ final Map<String,Object> ruleset2 = new HashMap<>();
+ ruleset2.put(AttributeTranscoderRegistry.PROP_ID, "foo");
+ ruleset2.put(AttributeTranscoderRegistry.PROP_TRANSCODER_CLASS,
+ "net.shibboleth.idp.attribute.transcoding.impl.PairTranscoder");
+ ruleset2.put("name", "baz");
+
+ final Map<String,Object> ruleset3 = new HashMap<>();
+ ruleset3.put(AttributeTranscoderRegistry.PROP_ID, "foo");
+ ruleset3.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ ruleset3.put(AttributeTranscoderRegistry.PROP_CONDITION, Predicates.alwaysFalse());
+ ruleset3.put("name", "ban");
+
+ final Map<String,Object> ruleset4 = new HashMap<>();
+ ruleset4.put(AttributeTranscoderRegistry.PROP_ID, "foo2");
+ ruleset4.put(AttributeTranscoderRegistry.PROP_TRANSCODER_CLASS,
+ "net.shibboleth.idp.attribute.transcoding.impl.PairTranscoder");
+ ruleset4.put("name", "baz");
+
+ registry.setTranscoderRegistry(Arrays.asList(
+ new TranscodingRule(ruleset1),
+ new TranscodingRule(ruleset2),
+ new TranscodingRule(ruleset3),
+ new TranscodingRule(ruleset4)));
+
+ registry.initialize();
+ }
+
+ @AfterClass public void tearDown() {
+ registry.destroy();
+ registry = null;
+ }
+
+
+ @Test public void testEncodeNoMappings() throws AttributeEncodingException {
+
+ assertTrue(registry.getTranscodingRules(new IdPAttribute("frobnitz"), Pair.class).isEmpty());
+ assertTrue(registry.getTranscodingRules(new IdPAttribute("frobnitz"), MyPair.class).isEmpty());
+ assertTrue(registry.getTranscodingRules(new IdPAttribute("foo"), String.class).isEmpty());
+}
+
+ @Test public void testDecodeNoMappings() throws AttributeDecodingException {
+
+ assertTrue(registry.getTranscodingRules(new Pair("foo", "value")).isEmpty());
+ assertTrue(registry.getTranscodingRules(new MyPair("foo", "value")).isEmpty());
+ assertTrue(registry.getTranscodingRules(new String("bar")).isEmpty());
+ }
+
+ @Test public void testDecodeInactive() throws AttributeDecodingException {
+
+ final Pair p = new Pair("ban", "value");
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(p);
+ assertEquals(rulesets.size(), 1);
+
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ assertNull(t.decode(null, p, ruleset));
+ }
+
+ @Test public void testEncodeNoValues() throws AttributeEncodingException {
+ final IdPAttribute foo = new IdPAttribute("foo");
+
+ final List<Pair> pairs = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(foo, Pair.class)) {
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ final Pair p = t.encode(null, foo, Pair.class, ruleset);
+ if (p != null) {
+ pairs.add(p);
+ }
+ }
+
+ assertEquals(pairs.size(), 2);
+
+ assertEquals(pairs.get(0).getFirst(), "bar");
+ assertNull(pairs.get(0).getSecond());
+
+ assertEquals(pairs.get(1).getFirst(), "baz");
+ assertNull(pairs.get(1).getSecond());
+ }
+
+ @Test public void testDecodeOneNoValues() throws AttributeDecodingException {
+
+ final Pair bar = new Pair("bar", null);
+
+ final List<IdPAttribute> attributes = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(bar)) {
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ attributes.add(t.decode(null, bar, ruleset));
+ }
+
+ assertEquals(attributes.size(), 1);
+
+ assertEquals(attributes.get(0).getId(), "foo");
+ assertTrue(attributes.get(0).getValues().isEmpty());
+ }
+
+ @Test public void testDecodeTwoNoValues() throws AttributeDecodingException {
+
+ final Pair baz = new Pair("baz", null);
+
+ final List<IdPAttribute> attributes = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(baz)) {
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ attributes.add(t.decode(null, baz, ruleset));
+ }
+
+ assertEquals(attributes.size(), 2);
+
+ assertEquals(attributes.get(0).getId(), "foo");
+ assertTrue(attributes.get(0).getValues().isEmpty());
+
+ assertEquals(attributes.get(1).getId(), "foo2");
+ assertTrue(attributes.get(1).getValues().isEmpty());
+ }
+
+ @Test public void testEncodeStringValues() throws AttributeEncodingException {
+ final IdPAttribute foo = new IdPAttribute("foo");
+ foo.setValues(Collections.singletonList(StringAttributeValue.valueOf("value")));
+
+ final List<Pair> pairs = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(foo, Pair.class)) {
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ final Pair p = t.encode(null, foo, Pair.class, ruleset);
+ if (p != null) {
+ pairs.add(p);
+ }
+ }
+
+ assertEquals(pairs.size(), 2);
+
+ assertEquals(pairs.get(0).getFirst(), "bar");
+ assertEquals(pairs.get(0).getSecond(), "value");
+
+ assertEquals(pairs.get(1).getFirst(), "baz");
+ assertEquals(pairs.get(1).getSecond(), "value");
+ }
+
+ @Test public void testEncodeSubtypeStringValues() throws AttributeEncodingException {
+ final IdPAttribute foo = new IdPAttribute("foo");
+ foo.setValues(Collections.singletonList(StringAttributeValue.valueOf("value")));
+
+ final List<MyPair> pairs = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(foo, MyPair.class)) {
+ final AttributeTranscoder<MyPair> t = TranscoderSupport.getTranscoder(ruleset);
+ final MyPair p = t.encode(null, foo, MyPair.class, ruleset);
+ if (p != null) {
+ pairs.add(p);
+ }
+ }
+
+ assertEquals(pairs.size(), 2);
+
+ assertEquals(pairs.get(0).getFirst(), "bar");
+ assertEquals(pairs.get(0).getSecond(), "value");
+
+ assertEquals(pairs.get(1).getFirst(), "baz");
+ assertEquals(pairs.get(1).getSecond(), "value");
+ }
+
+ @Test public void testDecodeOneStringValues() throws AttributeDecodingException {
+
+ final Pair bar = new Pair("bar", "value");
+
+ final List<IdPAttribute> attributes = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(bar)) {
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ attributes.add(t.decode(null, bar, ruleset));
+ }
+
+ assertEquals(attributes.size(), 1);
+
+ assertEquals(attributes.get(0).getId(), "foo");
+ assertEquals(attributes.get(0).getValues().get(0).getValue(), "value");
+ }
+
+ @Test public void testDecodeTwoStringValues() throws AttributeDecodingException {
+
+ final Pair baz = new Pair("baz", "value");
+
+ final List<IdPAttribute> attributes = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(baz)) {
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ attributes.add(t.decode(null, baz, ruleset));
+ }
+
+ assertEquals(attributes.size(), 2);
+
+ assertEquals(attributes.get(0).getId(), "foo");
+ assertEquals(attributes.get(0).getValues().get(0).getValue(), "value");
+
+ assertEquals(attributes.get(1).getId(), "foo2");
+ assertEquals(attributes.get(1).getValues().get(0).getValue(), "value");
+ }
+
+ @Test public void testEncodeUnsupportedValues() throws AttributeEncodingException {
+ final IdPAttribute foo = new IdPAttribute("foo");
+ foo.setValues(Collections.singletonList(EmptyAttributeValue.ZERO_LENGTH));
+
+ final List<Pair> pairs = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(foo, Pair.class)) {
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ final Pair p = t.encode(null, foo, Pair.class, ruleset);
+ if (p != null) {
+ pairs.add(p);
+ }
+ }
+
+ assertEquals(pairs.size(), 2);
+
+ assertEquals(pairs.get(0).getFirst(), "bar");
+ assertNull(pairs.get(0).getSecond());
+
+ assertEquals(pairs.get(1).getFirst(), "baz");
+ assertNull(pairs.get(0).getSecond());
+ }
+
+ @Test public void testDecodeOneUnsupportedValues() throws AttributeDecodingException {
+
+ final Pair bar = new Pair("bar", 0L);
+
+ final List<IdPAttribute> attributes = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(bar)) {
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ attributes.add(t.decode(null, bar, ruleset));
+ }
+
+ assertEquals(attributes.size(), 1);
+
+ assertEquals(attributes.get(0).getId(), "foo");
+ assertTrue(attributes.get(0).getValues().isEmpty());
+ }
+
+ @Test public void testDecodeTwoUnsupportedValues() throws AttributeDecodingException {
+
+ final Pair baz = new Pair("baz", 0L);
+
+ final List<IdPAttribute> attributes = new ArrayList<>();
+
+ for (final TranscodingRule ruleset : registry.getTranscodingRules(baz)) {
+ final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
+ attributes.add(t.decode(null, baz, ruleset));
+ }
+
+ assertEquals(attributes.size(), 2);
+
+ assertEquals(attributes.get(0).getId(), "foo");
+ assertTrue(attributes.get(0).getValues().isEmpty());
+
+ assertEquals(attributes.get(1).getId(), "foo2");
+ assertTrue(attributes.get(1).getValues().isEmpty());
+ }
+
+ /** Marker class to exercise subtype support. */
+
+ public static class MyPair extends Pair {
+ public MyPair(Object one, Object two) {
+ super(one, two);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/PairTranscoder.java b/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/PairTranscoder.java
new file mode 100644
index 0000000..abe4e10
--- /dev/null
+++ b/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/PairTranscoder.java
@@ -0,0 +1,102 @@
+/*
+ * 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.idp.attribute.transcoding.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.AbstractAttributeTranscoder;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.utilities.java.support.collection.Pair;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * Sample transcoder for tests.
+ */
+public class PairTranscoder extends AbstractAttributeTranscoder<Pair> {
+
+ /** {@inheritDoc} */
+ public Class<Pair> getEncodedType() {
+ return Pair.class;
+ }
+
+ /** {@inheritDoc} */
+ public String getEncodedName(TranscodingRule rule) {
+ final String name = rule.get("name", String.class);
+ if (name != null) {
+ return "{Pair}" + name;
+ } else {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Pair doEncode(ProfileRequestContext profileRequestContext, IdPAttribute attribute, Class<? extends Pair> to, TranscodingRule rule)
+ throws AttributeEncodingException {
+
+ final String name = StringSupport.trimOrNull(rule.get("name", String.class));
+ if (name == null) {
+ throw new AttributeEncodingException("No name property");
+ }
+
+ try {
+ if (attribute.getValues().isEmpty() || !canEncodeValue(attribute, attribute.getValues().get(0))) {
+ return to.getDeclaredConstructor(Object.class, Object.class).newInstance(name, null);
+ } else {
+ return to.getDeclaredConstructor(Object.class, Object.class).newInstance(name, attribute.getValues().get(0).getValue());
+ }
+ } catch (final InstantiationException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException | SecurityException e) {
+ throw new AttributeEncodingException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public IdPAttribute doDecode(ProfileRequestContext profileRequestContext, Pair input, TranscodingRule rule)
+ throws AttributeDecodingException {
+
+ final String id = StringSupport.trimOrNull(rule.get(AttributeTranscoderRegistry.PROP_ID, String.class));
+ if (id == null) {
+ throw new AttributeDecodingException("No id property");
+ }
+
+ final IdPAttribute idattr = new IdPAttribute(id);
+
+ if (input.getSecond() instanceof String) {
+ idattr.setValues(Collections.singletonList(StringAttributeValue.valueOf((String) input.getSecond())));
+ }
+
+ return idattr;
+ }
+
+ /** {@inheritDoc} */
+ protected boolean canEncodeValue(IdPAttribute idpAttribute, IdPAttributeValue value) {
+ return value instanceof StringAttributeValue;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-api/.project b/idp-attribute-resolver-api/.project
index f1c493c..de89ab8 100644
--- a/idp-attribute-resolver-api/.project
+++ b/idp-attribute-resolver-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AbstractAttributeDefinition.java b/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AbstractAttributeDefinition.java
index 8202da9..0c2f8c5 100644
--- a/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AbstractAttributeDefinition.java
+++ b/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AbstractAttributeDefinition.java
@@ -19,18 +19,15 @@ package net.shibboleth.idp.attribute.resolver;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Set;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
import net.shibboleth.idp.attribute.resolver.context.AttributeResolverWorkContext;
@@ -38,7 +35,6 @@ import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElemen
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.annotation.constraint.NullableElements;
import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
-import net.shibboleth.utilities.java.support.collection.CollectionSupport;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
@@ -46,9 +42,7 @@ import net.shibboleth.utilities.java.support.primitive.StringSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
/** Base class for attribute definition resolver plugins. */
@ThreadSafe
@@ -61,9 +55,6 @@ public abstract class AbstractAttributeDefinition extends AbstractResolverPlugin
/** Whether this attribute definition is only a dependency and thus its values should never be released. */
private boolean dependencyOnly;
- /** Attribute encoders associated with this definition. */
- @Nonnull private Set<AttributeEncoder<?>> encoders = Collections.emptySet();
-
/** Localized human intelligible attribute name. */
@Nonnull private Map<Locale, String> displayNames = Collections.emptyMap();
@@ -159,31 +150,6 @@ public abstract class AbstractAttributeDefinition extends AbstractResolverPlugin
displayNames = ImmutableMap.copyOf(checkedNames);
}
- /**
- * Gets the unmodifiable encoders used to encode the values of this attribute in to protocol specific formats. The
- * returned collection is never null nor contains any null.
- *
- * @return encoders used to encode the values of this attribute in to protocol specific formats, never null
- */
- @Override
- @Nonnull @NonnullElements @Unmodifiable public Set<AttributeEncoder<?>> getAttributeEncoders() {
- return encoders;
- }
-
- /**
- * Sets the encoders used to encode the values of this attribute in to protocol specific formats.
- *
- * @param attributeEncoders encoders used to encode the values of this attribute in to protocol specific formats
- */
- public void setAttributeEncoders(@Nullable @NullableElements final Set<AttributeEncoder<?>> attributeEncoders) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
-
- final Set<AttributeEncoder<?>> checkedEncoders = new HashSet<>();
- CollectionSupport.addIf(checkedEncoders, attributeEncoders, Predicates.notNull());
- encoders = ImmutableSet.copyOf(checkedEncoders);
- }
-
/** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
@@ -235,10 +201,6 @@ public abstract class AbstractAttributeDefinition extends AbstractResolverPlugin
getDisplayNames());
resolvedAttribute.setDisplayNames(getDisplayNames());
- log.trace("{} associating the following encoders with the resolved attribute: {}", getLogPrefix(),
- getAttributeEncoders());
- resolvedAttribute.setEncoders(getAttributeEncoders());
-
return resolvedAttribute;
}
diff --git a/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AttributeDefinition.java b/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AttributeDefinition.java
index 4e66a8b..27a4850 100644
--- a/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AttributeDefinition.java
+++ b/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AttributeDefinition.java
@@ -19,11 +19,9 @@ package net.shibboleth.idp.attribute.resolver;
import java.util.Locale;
import java.util.Map;
-import java.util.Set;
import javax.annotation.concurrent.ThreadSafe;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
@@ -55,12 +53,4 @@ public interface AttributeDefinition extends ResolverPlugin<IdPAttribute> {
*/
@NonnullAfterInit @NonnullElements @Unmodifiable Map<Locale, String> getDisplayNames();
- /**
- * Gets the unmodifiable encoders used to encode the values of this attribute in to protocol specific formats. The
- * returned collection is never null nor contains any null.
- *
- * @return encoders used to encode the values of this attribute in to protocol specific formats, never null
- */
- @NonnullAfterInit @NonnullElements @Unmodifiable Set<AttributeEncoder<?>> getAttributeEncoders();
-
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AttributeResolver.java b/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AttributeResolver.java
index 1c7c8b3..ead6668 100644
--- a/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AttributeResolver.java
+++ b/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/AttributeResolver.java
@@ -17,14 +17,10 @@
package net.shibboleth.idp.attribute.resolver;
-import java.util.Collection;
-
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
-import net.shibboleth.utilities.java.support.collection.Pair;
import net.shibboleth.utilities.java.support.component.IdentifiedComponent;
/**
@@ -40,14 +36,6 @@ import net.shibboleth.utilities.java.support.component.IdentifiedComponent;
public interface AttributeResolver extends IdentifiedComponent {
/**
- * Gets all the {@link AttributeEncoder}s for this resolver. Each encoder is linked
- * (via being in an {@link Pair} to the name of the attribute it is associated with.
- *
- * @return The Attribute Encoders loaded in to this resolver
- */
- @Nonnull Collection<Pair<String, AttributeEncoder<?>>> getAllEncoders();
-
- /**
* Resolves the attribute for the give request. Note, if attributes are requested,
* {@link AttributeResolutionContext#getRequestedIdPAttributeNames()}, the resolver will <strong>not</strong> fail
* if they can not be resolved. This information serves only as a hint to the resolver to, potentially, optimize the
diff --git a/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/ResolvedAttributeDefinition.java b/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/ResolvedAttributeDefinition.java
index 43e35d6..a382b7f 100644
--- a/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/ResolvedAttributeDefinition.java
+++ b/idp-attribute-resolver-api/src/main/java/net/shibboleth/idp/attribute/resolver/ResolvedAttributeDefinition.java
@@ -26,7 +26,6 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
import net.shibboleth.idp.attribute.resolver.context.AttributeResolverWorkContext;
@@ -78,11 +77,6 @@ public final class ResolvedAttributeDefinition extends AbstractAttributeDefiniti
}
/** {@inheritDoc} */
- @Override @Nonnull @NonnullElements public Set<AttributeEncoder<?>> getAttributeEncoders() {
- return resolvedDefinition.getAttributeEncoders();
- }
-
- /** {@inheritDoc} */
@Override @Nonnull @NonnullElements public Set<ResolverAttributeDefinitionDependency> getAttributeDependencies() {
return resolvedDefinition.getAttributeDependencies();
}
diff --git a/idp-attribute-resolver-api/src/test/java/net/shibboleth/idp/attribute/resolver/AbstractAttributeDefinitionTest.java b/idp-attribute-resolver-api/src/test/java/net/shibboleth/idp/attribute/resolver/AbstractAttributeDefinitionTest.java
index 67fe772..3ddab43 100644
--- a/idp-attribute-resolver-api/src/test/java/net/shibboleth/idp/attribute/resolver/AbstractAttributeDefinitionTest.java
+++ b/idp-attribute-resolver-api/src/test/java/net/shibboleth/idp/attribute/resolver/AbstractAttributeDefinitionTest.java
@@ -19,7 +19,6 @@ package net.shibboleth.idp.attribute.resolver;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -27,7 +26,6 @@ import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
import net.shibboleth.idp.attribute.resolver.context.AttributeResolverWorkContext;
@@ -49,8 +47,6 @@ public class AbstractAttributeDefinitionTest {
Assert.assertEquals(definition.getId(), "foo");
Assert.assertFalse(definition.isDependencyOnly());
- Assert.assertNotNull(definition.getAttributeEncoders());
- Assert.assertTrue(definition.getAttributeEncoders().isEmpty());
Assert.assertNotNull(definition.getDisplayDescriptions());
Assert.assertTrue(definition.getDisplayDescriptions().isEmpty());
Assert.assertNotNull(definition.getDisplayNames());
@@ -76,50 +72,6 @@ public class AbstractAttributeDefinitionTest {
Assert.assertFalse(definition.isDependencyOnly());
}
- /** Tests setting and retrieving encoders. */
- @Test
- public void encoders() {
- MockAttributeDefinition definition = new MockAttributeDefinition("foo", null);
-
- MockAttributeEncoder enc1 = new MockAttributeEncoder(null, null);
- MockAttributeEncoder enc2 = new MockAttributeEncoder(null, null);
-
- Set<AttributeEncoder<?>> encoders = new HashSet<>(2);
-
- definition.setAttributeEncoders(null);
- Assert.assertNotNull(definition.getAttributeEncoders());
- Assert.assertTrue(definition.getAttributeEncoders().isEmpty());
-
- definition.setAttributeEncoders(encoders);
- Assert.assertNotNull(definition.getAttributeEncoders());
- Assert.assertTrue(definition.getAttributeEncoders().isEmpty());
-
- encoders.add(enc1);
- encoders.add(null);
- encoders.add(enc2);
- Assert.assertNotNull(definition.getAttributeEncoders());
- Assert.assertTrue(definition.getAttributeEncoders().isEmpty());
-
- definition.setAttributeEncoders(encoders);
- Assert.assertEquals(definition.getAttributeEncoders().size(), 2);
- Assert.assertTrue(definition.getAttributeEncoders().contains(enc1));
- Assert.assertTrue(definition.getAttributeEncoders().contains(enc2));
-
- encoders.clear();
- encoders.add(enc2);
- definition.setAttributeEncoders(encoders);
- Assert.assertEquals(definition.getAttributeEncoders().size(), 1);
- Assert.assertFalse(definition.getAttributeEncoders().contains(enc1));
- Assert.assertTrue(definition.getAttributeEncoders().contains(enc2));
-
- try {
- definition.getAttributeEncoders().add(enc2);
- Assert.fail("able to add entry to supposedly unmodifiable collection");
- } catch (UnsupportedOperationException e) {
- // expected this
- }
- }
-
/** Tests that display descriptions are properly added and modified. */
@Test
public void displayDescriptions() {
@@ -228,30 +180,6 @@ public class AbstractAttributeDefinitionTest {
testInvalidName(new MockAttributeDefinition("Name\rWith\tnonprinters", (IdPAttribute) null));
}
- @Test public void initDestroyValidate() throws ComponentInitializationException {
- MockAttributeEncoder encoder = new MockAttributeEncoder("foo", "baz");
- MockAttributeDefinition definition = new MockAttributeDefinition("foo", (IdPAttribute) null);
-
- Set<AttributeEncoder<?>> encoders = new HashSet<>(1);
- encoders.add(encoder);
- definition.setAttributeEncoders(encoders);
-
- Assert.assertFalse(encoder.isInitialized());
- Assert.assertFalse(encoder.isDestroyed());
-
- encoder.initialize();
- definition.initialize();
- Assert.assertTrue(encoder.isInitialized());
- Assert.assertFalse(encoder.isDestroyed());
-
- definition.destroy();
- encoder.destroy();
- Assert.assertTrue(encoder.isInitialized());
- Assert.assertTrue(encoder.isDestroyed());
-
-
- }
-
/**
* This class implements the minimal level of functionality and is meant only as a means of testing the abstract
* {@link AttributeDefinition}.
diff --git a/idp-attribute-resolver-api/src/test/java/net/shibboleth/idp/attribute/resolver/MockAttributeEncoder.java b/idp-attribute-resolver-api/src/test/java/net/shibboleth/idp/attribute/resolver/MockAttributeEncoder.java
deleted file mode 100644
index 8eb77b2..0000000
--- a/idp-attribute-resolver-api/src/test/java/net/shibboleth/idp/attribute/resolver/MockAttributeEncoder.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.idp.attribute.resolver;
-
-import java.util.function.Predicate;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-
-import com.google.common.base.Predicates;
-
-import net.shibboleth.idp.attribute.AttributeEncoder;
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
-
-/** Mock implementation of {@link AttributeEncoder}. */
-public class MockAttributeEncoder extends AbstractInitializableComponent implements AttributeEncoder<String> {
-
- /** Static protocol value for this encoder. */
- private final String staticProtocol;
-
- /** Static value for this encoder. */
- private final String staticValue;
-
- /**
- * Constructor.
- *
- * @param protocol protocol value returned by {@link #getProtocol()}
- * @param value value returned by {@link #encode(IdPAttribute)}
- */
- public MockAttributeEncoder(String protocol, String value) {
- staticProtocol = protocol;
- staticValue = value;
- }
-
- /** {@inheritDoc} */
- public String getProtocol() {
- return staticProtocol;
- }
-
- /** {@inheritDoc} */
- public String encode(IdPAttribute attribute) throws AttributeEncodingException {
- return staticValue;
- }
-
- /** {@inheritDoc} */
- public Predicate<ProfileRequestContext> getActivationCondition() {
- return Predicates.alwaysTrue();
- }
-
-}
\ No newline at end of file
diff --git a/idp-attribute-resolver-impl/.project b/idp-attribute-resolver-impl/.project
index dcea4b2..fe73535 100644
--- a/idp-attribute-resolver-impl/.project
+++ b/idp-attribute-resolver-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/impl/AttributeResolverImpl.java b/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/impl/AttributeResolverImpl.java
index d2168fe..fd41cd1 100644
--- a/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/impl/AttributeResolverImpl.java
+++ b/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/impl/AttributeResolverImpl.java
@@ -41,7 +41,6 @@ import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
import net.shibboleth.ext.spring.service.AbstractServiceableComponent;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.EmptyAttributeValue;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.IdPAttributeValue;
@@ -61,7 +60,6 @@ import net.shibboleth.utilities.java.support.annotation.constraint.NullableEleme
import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
import net.shibboleth.utilities.java.support.collection.LazyList;
import net.shibboleth.utilities.java.support.collection.LazySet;
-import net.shibboleth.utilities.java.support.collection.Pair;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
@@ -632,15 +630,4 @@ public class AttributeResolverImpl extends AbstractServiceableComponent<Attribut
}
}
- /** {@inheritDoc} */
- public Collection<Pair<String, AttributeEncoder<?>>> getAllEncoders() {
- final Collection<Pair<String, AttributeEncoder<?>>> result = new HashSet<>();
-
- for (final AttributeDefinition attributeDef : getAttributeDefinitions().values()) {
- for (final AttributeEncoder encoder : attributeDef.getAttributeEncoders()) {
- result.add(new Pair<>(attributeDef.getId(), encoder));
- }
- }
- return result;
- }
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/.project b/idp-attribute-resolver-spring/.project
index e323203..d7c71e4 100644
--- a/idp-attribute-resolver-spring/.project
+++ b/idp-attribute-resolver-spring/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/BaseAttributeDefinitionParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/BaseAttributeDefinitionParser.java
index 5b83ed8..0e85bc5 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/BaseAttributeDefinitionParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/BaseAttributeDefinitionParser.java
@@ -31,7 +31,6 @@ import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
-import net.shibboleth.ext.spring.util.SpringSupport;
import net.shibboleth.idp.attribute.resolver.spring.BaseResolverPluginParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
@@ -87,16 +86,6 @@ public abstract class BaseAttributeDefinitionParser extends BaseResolverPluginPa
log.debug("{} Setting dependencyOnly {}", getLogPrefix(), dependencyOnly);
builder.addPropertyValue("dependencyOnly", dependencyOnly);
}
-
- final List<Element> attributeEncoders =
- ElementSupport.getChildElements(config, new QName(AttributeResolverNamespaceHandler.NAMESPACE,
- "AttributeEncoder"));
-
- if (attributeEncoders != null && !attributeEncoders.isEmpty()) {
- log.debug("{} Adding {} encoders", getLogPrefix(), attributeEncoders.size());
- builder.addPropertyValue("attributeEncoders",
- SpringSupport.parseCustomElements(attributeEncoders, parserContext));
- }
}
// CheckStyle: CyclomaticComplexity ON
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseAttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseAttributeEncoderParser.java
index 0250547..880adfe 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseAttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseAttributeEncoderParser.java
@@ -17,11 +17,13 @@
package net.shibboleth.idp.attribute.resolver.spring.enc;
+import java.util.Map;
+
import javax.annotation.Nonnull;
-import net.shibboleth.ext.spring.util.SpringSupport;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
-import net.shibboleth.idp.profile.logic.RelyingPartyIdPredicate;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
import net.shibboleth.idp.profile.logic.ScriptedPredicate;
import net.shibboleth.idp.profile.spring.relyingparty.metadata.ScriptTypeBeanParser;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
@@ -30,8 +32,10 @@ import net.shibboleth.utilities.java.support.xml.ElementSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
@@ -47,77 +51,77 @@ public abstract class BaseAttributeEncoderParser extends AbstractSingleBeanDefin
/** Log4j logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(BaseAttributeEncoderParser.class);
- /** Whether the name property is required or not. */
- private boolean nameRequired;
-
- /** Constructor. */
- public BaseAttributeEncoderParser() {
- nameRequired = false;
+ /** {@inheritDoc} */
+ @Override
+ protected Class<TranscodingRule> getBeanClass(final Element element) {
+ return TranscodingRule.class;
}
-
- /**
- * Set whether the name property is required or not.
- *
- * @param flag flag to set
- */
- public void setNameRequired(final boolean flag) {
- nameRequired = flag;
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean shouldGenerateId() {
+ return true;
}
/** {@inheritDoc} */
- @Override protected void doParse(final Element config, final ParserContext parserContext,
- final BeanDefinitionBuilder builder) {
+ @Override
+ protected boolean shouldParseNameAsAliases() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doParse(final Element config, final ParserContext context, final BeanDefinitionBuilder builder) {
+
+ final ManagedMap rule = new ManagedMap();
- super.doParse(config, parserContext, builder);
+ builder.addConstructorArgValue(rule);
- final String attributeName = StringSupport.trimOrNull(config.getAttributeNS(null, NAME_ATTRIBUTE_NAME));
- if (nameRequired && attributeName == null) {
- throw new BeanCreationException("Attribute encoder must contain a name property");
+ if (config.getParentNode() instanceof Element && ((Element)config.getParentNode()).hasAttributeNS(null, "id")) {
+ rule.put(AttributeTranscoderRegistry.PROP_ID,
+ StringSupport.trimOrNull(((Element) config.getParentNode()).getAttributeNS(null, "id")));
+ } else {
+ log.warn("Parsing AttributeEncoder with no parent element, resulting rule will be ignored");
}
if (config.hasAttributeNS(null, "activationConditionRef")) {
if (config.hasAttributeNS(null, "relyingParties")) {
log.warn("relyingParties ignored, using activationConditionRef");
}
- builder.addPropertyReference("activationCondition",
- StringSupport.trimOrNull(config.getAttributeNS(null, "activationConditionRef")));
+ rule.put(AttributeTranscoderRegistry.PROP_CONDITION, new RuntimeBeanReference(
+ StringSupport.trimOrNull(config.getAttributeNS(null, "activationConditionRef"))));
} else if (config.hasAttributeNS(null, "relyingParties")) {
- final BeanDefinitionBuilder rpBuilder =
- BeanDefinitionBuilder.genericBeanDefinition(RelyingPartyIdPredicate.class);
- rpBuilder.setFactoryMethod("fromCandidates");
- rpBuilder .addConstructorArgValue(
- SpringSupport.getAttributeValueAsList(config.getAttributeNodeNS(null, "relyingParties")));
- builder.addPropertyValue("activationCondition", rpBuilder.getBeanDefinition());
+ rule.put(AttributeTranscoderRegistry.PROP_RELYINGPARTIES, config.getAttributeNS(null, "relyingParties"));
} else {
final Element child = ElementSupport.getFirstChildElement(config);
if (child != null && ElementSupport.isElementNamed(child,
AttributeResolverNamespaceHandler.NAMESPACE, "ActivationConditionScript")) {
- builder.addPropertyValue("activationCondition",
+ rule.put(AttributeTranscoderRegistry.PROP_CONDITION,
ScriptTypeBeanParser.parseScriptType(ScriptedPredicate.class, child).getBeanDefinition());
}
}
- if (config.hasAttributeNS(null, "encodeType")) {
- builder.addPropertyValue("encodeType", StringSupport.trimOrNull(config.getAttributeNS(null, "encodeType")));
- }
-
- builder.setInitMethodName("initialize");
- builder.setDestroyMethodName("destroy");
- builder.addPropertyValue("name", attributeName);
-
+ rule.put(AttributeTranscoderRegistry.PROP_TRANSCODER, buildTranscoder());
+
+ doParse(config, context, rule);
}
+
+ /**
+ * Inject any necessary elements into the mapping rule based on the specific encoder type.
+ *
+ * @param config the encoder element being parsed
+ * @param parserContext the parser context
+ * @param rule the mapping rule
+ */
+ protected abstract void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
+ @Nonnull final Map<String,Object> rule);
- /** {@inheritDoc} */
- @Override public boolean shouldGenerateId() {
- return true;
- }
/**
- * {@inheritDoc}. <br/>
- * We parse the attribute "name" and we do not want Spring to. see #IDP-571.
+ * Return a bean definition for the transcoder to include in the mapping.
+ *
+ * @return bean definition for an AttributeTranscoder
*/
- @Override protected boolean shouldParseNameAsAliases() {
- return false;
- }
-
+ @Nonnull protected abstract BeanReference buildTranscoder();
+
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseSAML1AttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseSAML1AttributeEncoderParser.java
new file mode 100644
index 0000000..95af88e
--- /dev/null
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseSAML1AttributeEncoderParser.java
@@ -0,0 +1,61 @@
+/*
+ * 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.idp.attribute.resolver.spring.enc;
+
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+import net.shibboleth.ext.spring.util.SpringSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * Base class for Spring bean definition parser for SAML 1 attribute encoders.
+ */
+public abstract class BaseSAML1AttributeEncoderParser extends BaseAttributeEncoderParser {
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
+ @Nonnull final Map<String,Object> rule) {
+
+ if (config.hasAttributeNS(null, "name")) {
+ rule.put(SAMLAttributeTranscoder.PROP_NAME,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "name")));
+ } else {
+ throw new BeanDefinitionStoreException("Missing 'name' attribute, cannot create transcoder rule");
+ }
+
+ if (config.hasAttributeNS(null, "namespace")) {
+ rule.put(SAML1AttributeTranscoder.PROP_NAMESPACE,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "namespace")));
+ }
+
+ final String value = StringSupport.trimOrNull(config.getAttributeNS(null, "encodeType"));
+ if (value != null) {
+ rule.put(SAMLAttributeTranscoder.PROP_ENCODE_TYPE,SpringSupport.getStringValueAsBoolean(value));
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseSAML2AttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseSAML2AttributeEncoderParser.java
new file mode 100644
index 0000000..2410a8a
--- /dev/null
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseSAML2AttributeEncoderParser.java
@@ -0,0 +1,65 @@
+/*
+ * 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.idp.attribute.resolver.spring.enc;
+
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+import net.shibboleth.ext.spring.util.SpringSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * Base class for Spring bean definition parser for SAML 1 attribute encoders.
+ */
+public abstract class BaseSAML2AttributeEncoderParser extends BaseAttributeEncoderParser {
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
+ @Nonnull final Map<String,Object> rule) {
+
+ if (config.hasAttributeNS(null, "name")) {
+ rule.put(SAMLAttributeTranscoder.PROP_NAME,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "name")));
+ } else {
+ throw new BeanDefinitionStoreException("Missing 'name' attribute, cannot create transcoder rule");
+ }
+
+ if (config.hasAttributeNS(null, "nameFormat")) {
+ rule.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "nameFormat")));
+ }
+
+ if (config.hasAttributeNS(null, "friendlyName")) {
+ rule.put(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "friendlyName")));
+ }
+
+ final String value = StringSupport.trimOrNull(config.getAttributeNS(null, "encodeType"));
+ if (value != null) {
+ rule.put(SAMLAttributeTranscoder.PROP_ENCODE_TYPE,SpringSupport.getStringValueAsBoolean(value));
+ }
+ }
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseScopedAttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseScopedAttributeEncoderParser.java
deleted file mode 100644
index 18aea46..0000000
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseScopedAttributeEncoderParser.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.idp.attribute.resolver.spring.enc;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Element;
-
-/**
- * Base class for Spring bean definition parser for Shibboleth scoped attribute encoders.
- */
-public abstract class BaseScopedAttributeEncoderParser extends BaseAttributeEncoderParser {
-
- /** Local name of scope type attribute. */
- @Nonnull @NotEmpty public static final String SCOPE_TYPE_ATTRIBUTE_NAME = "scopeType";
-
- /** Local name of scope delimiter attribute. */
- @Nonnull @NotEmpty public static final String SCOPE_DELIMITER_ATTRIBUTE_NAME = "scopeDelimiter";
-
- /** Local name of scope attribute attribute. */
- @Nonnull @NotEmpty public static final String SCOPE_ATTRIBUTE_ATTRIBUTE_NAME = "scopeAttribute";
-
- /** {@inheritDoc} */
- @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
- @Nonnull final BeanDefinitionBuilder builder) {
- super.doParse(config, parserContext, builder);
-
- if (config.hasAttributeNS(null, SCOPE_DELIMITER_ATTRIBUTE_NAME)) {
- builder.addPropertyValue("scopeDelimiter",
- StringSupport.trimOrNull(config.getAttributeNS(null, SCOPE_DELIMITER_ATTRIBUTE_NAME)));
- }
-
- if (config.hasAttributeNS(null, SCOPE_ATTRIBUTE_ATTRIBUTE_NAME)) {
- builder.addPropertyValue("scopeAttributeName",
- StringSupport.trimOrNull(config.getAttributeNS(null, SCOPE_ATTRIBUTE_ATTRIBUTE_NAME)));
- }
- }
-
-}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1Base64AttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1Base64AttributeEncoderParser.java
index fd06ee2..6cfe0b1 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1Base64AttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1Base64AttributeEncoderParser.java
@@ -18,49 +18,28 @@
package net.shibboleth.idp.attribute.resolver.spring.enc.impl;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.xml.namespace.QName;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Element;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
-import net.shibboleth.idp.attribute.resolver.spring.enc.BaseAttributeEncoderParser;
+import net.shibboleth.idp.attribute.resolver.spring.enc.BaseSAML1AttributeEncoderParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1ByteAttributeEncoder;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ByteAttributeTranscoder;
/**
- * Spring Bean Definition Parser for {@link SAML1ByteAttributeEncoder}.
+ * Spring Bean Definition Parser for {@link SAML1ByteAttributeTranscoder}.
*/
-public class SAML1Base64AttributeEncoderParser extends BaseAttributeEncoderParser {
+public class SAML1Base64AttributeEncoderParser extends BaseSAML1AttributeEncoderParser {
/** Schema type name. */
@Nonnull public static final QName TYPE_NAME_RESOLVER = new QName(AttributeResolverNamespaceHandler.NAMESPACE,
"SAML1Base64");
- /** Local name of namespace attribute. */
- @Nonnull @NotEmpty public static final String NAMESPACE_ATTRIBUTE_NAME = "namespace";
-
- /** Constructor. */
- public SAML1Base64AttributeEncoderParser() {
- setNameRequired(true);
- }
-
/** {@inheritDoc} */
- @Override protected Class<SAML1ByteAttributeEncoder> getBeanClass(@Nullable final Element element) {
- return SAML1ByteAttributeEncoder.class;
+ @Override
+ protected BeanReference buildTranscoder() {
+ return new RuntimeBeanReference("SAML1ByteTranscoder");
}
- /** {@inheritDoc} */
- @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
- @Nonnull final BeanDefinitionBuilder builder) {
- super.doParse(config, parserContext, builder);
-
- if (config.hasAttributeNS(null, NAMESPACE_ATTRIBUTE_NAME)) {
- final String namespace = StringSupport.trimOrNull(config.getAttributeNS(null, NAMESPACE_ATTRIBUTE_NAME));
- builder.addPropertyValue("namespace", namespace);
- }
- }
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1ScopedStringAttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1ScopedStringAttributeEncoderParser.java
index 3b39b37..5446ddf 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1ScopedStringAttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1ScopedStringAttributeEncoderParser.java
@@ -17,55 +17,55 @@
package net.shibboleth.idp.attribute.resolver.spring.enc.impl;
+import java.util.Map;
+
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.xml.namespace.QName;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
-import net.shibboleth.idp.attribute.resolver.spring.enc.BaseScopedAttributeEncoderParser;
+import net.shibboleth.idp.attribute.resolver.spring.enc.BaseSAML1AttributeEncoderParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1ScopedStringAttributeEncoder;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ScopedStringAttributeTranscoder;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
/**
- * Spring Bean Definition Parser for {@link SAML1ScopedStringAttributeEncoder}.
+ * Spring Bean Definition Parser for {@link SAML1ScopedStringAttributeTranscoder}.
*/
-public class SAML1ScopedStringAttributeEncoderParser extends BaseScopedAttributeEncoderParser {
+public class SAML1ScopedStringAttributeEncoderParser extends BaseSAML1AttributeEncoderParser {
/** Schema type name. */
@Nonnull public static final QName TYPE_NAME_RESOLVER = new QName(AttributeResolverNamespaceHandler.NAMESPACE,
"SAML1ScopedString");
- /** Local name of namespace attribute. */
- @Nonnull @NotEmpty public static final String NAMESPACE_ATTRIBUTE_NAME = "namespace";
-
- /** Constructor. */
- public SAML1ScopedStringAttributeEncoderParser() {
- setNameRequired(true);
- }
-
- /** {@inheritDoc} */
- @Override protected Class<SAML1ScopedStringAttributeEncoder> getBeanClass(@Nullable final Element element) {
- return SAML1ScopedStringAttributeEncoder.class;
- }
-
/** {@inheritDoc} */
@Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
- @Nonnull final BeanDefinitionBuilder builder) {
- super.doParse(config, parserContext, builder);
+ @Nonnull final Map<String,Object> rule) {
+ super.doParse(config, parserContext, rule);
- if (config.hasAttributeNS(null, SCOPE_TYPE_ATTRIBUTE_NAME)) {
- builder.addPropertyValue("scopeType",
- StringSupport.trimOrNull(config.getAttributeNS(null, SCOPE_TYPE_ATTRIBUTE_NAME)));
+ if (config.hasAttributeNS(null, "scopeType")) {
+ rule.put(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_TYPE,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "scopeType")));
+ }
+
+ if (config.hasAttributeNS(null, "scopeDelimiter")) {
+ rule.put(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "scopeDelimiter")));
}
- if (config.hasAttributeNS(null, NAMESPACE_ATTRIBUTE_NAME)) {
- final String namespace = StringSupport.trimOrNull(config.getAttributeNS(null, NAMESPACE_ATTRIBUTE_NAME));
- builder.addPropertyValue("namespace", namespace);
+ if (config.hasAttributeNS(null, "scopeAttribute")) {
+ rule.put(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_ATTR_NAME,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "scopeAttribute")));
}
}
+
+ /** {@inheritDoc} */
+ @Override
+ protected BeanReference buildTranscoder() {
+ return new RuntimeBeanReference("SAML1ScopedStringTranscoder");
+ }
+
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1StringAttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1StringAttributeEncoderParser.java
index a7a4768..e71f747 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1StringAttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1StringAttributeEncoderParser.java
@@ -18,55 +18,28 @@
package net.shibboleth.idp.attribute.resolver.spring.enc.impl;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.xml.namespace.QName;
-import org.springframework.beans.factory.BeanCreationException;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Element;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
-import net.shibboleth.idp.attribute.resolver.spring.enc.BaseAttributeEncoderParser;
+import net.shibboleth.idp.attribute.resolver.spring.enc.BaseSAML1AttributeEncoderParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1StringAttributeEncoder;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1StringAttributeTranscoder;
/**
- * Spring Bean Definition Parser for {@link SAML1StringAttributeEncoder}.
+ * Spring Bean Definition Parser for {@link SAML1StringAttributeTranscoder}.
*/
-public class SAML1StringAttributeEncoderParser extends BaseAttributeEncoderParser {
+public class SAML1StringAttributeEncoderParser extends BaseSAML1AttributeEncoderParser {
/** Schema type name.. */
@Nonnull public static final QName TYPE_NAME_RESOLVER = new QName(AttributeResolverNamespaceHandler.NAMESPACE,
"SAML1String");
- /** Local name of namespace attribute. */
- @Nonnull @NotEmpty public static final String NAMESPACE_ATTRIBUTE_NAME = "namespace";
-
- /** Constructor. */
- public SAML1StringAttributeEncoderParser() {
- setNameRequired(true);
- }
-
/** {@inheritDoc} */
- @Override protected Class<SAML1StringAttributeEncoder> getBeanClass(@Nullable final Element element) {
- return SAML1StringAttributeEncoder.class;
+ @Override
+ protected BeanReference buildTranscoder() {
+ return new RuntimeBeanReference("SAML1StringTranscoder");
}
- /** {@inheritDoc} */
- @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
- @Nonnull final BeanDefinitionBuilder builder) {
- super.doParse(config, parserContext, builder);
-
- if (config.hasAttributeNS(null, NAMESPACE_ATTRIBUTE_NAME)) {
- final String namespace = StringSupport.trimOrNull(config.getAttributeNS(null, NAMESPACE_ATTRIBUTE_NAME));
- builder.addPropertyValue("namespace", namespace);
- }
-
- final String attributeName = StringSupport.trimOrNull(config.getAttributeNS(null, "name"));
- if (attributeName == null) {
- throw new BeanCreationException("SAML 1 attribute encoders must contain a name");
- }
- }
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1XMLObjectAttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1XMLObjectAttributeEncoderParser.java
index 21ebb73..97a0309 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1XMLObjectAttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML1XMLObjectAttributeEncoderParser.java
@@ -18,47 +18,26 @@
package net.shibboleth.idp.attribute.resolver.spring.enc.impl;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.xml.namespace.QName;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Element;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
-import net.shibboleth.idp.attribute.resolver.spring.enc.BaseAttributeEncoderParser;
+import net.shibboleth.idp.attribute.resolver.spring.enc.BaseSAML1AttributeEncoderParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1XMLObjectAttributeEncoder;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1XMLObjectAttributeTranscoder;
-/** Spring Bean Definition Parser for {@link SAML1XMLObjectAttributeEncoder}. */
-public class SAML1XMLObjectAttributeEncoderParser extends BaseAttributeEncoderParser {
+/** Spring Bean Definition Parser for {@link SAML1XMLObjectAttributeTranscoder}. */
+public class SAML1XMLObjectAttributeEncoderParser extends BaseSAML1AttributeEncoderParser {
/** Schema type name.. */
@Nonnull public static final QName TYPE_NAME_RESOLVER =
new QName(AttributeResolverNamespaceHandler.NAMESPACE, "SAML1XMLObject");
- /** Local name of namespace attribute. */
- @Nonnull @NotEmpty public static final String NAMESPACE_ATTRIBUTE_NAME = "namespace";
-
- /** Constructor. */
- public SAML1XMLObjectAttributeEncoderParser() {
- setNameRequired(true);
- }
-
/** {@inheritDoc} */
- @Override protected Class<SAML1XMLObjectAttributeEncoder> getBeanClass(@Nullable final Element element) {
- return SAML1XMLObjectAttributeEncoder.class;
+ @Override
+ protected BeanReference buildTranscoder() {
+ return new RuntimeBeanReference("SAML1XMLObjectTranscoder");
}
- /** {@inheritDoc} */
- @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
- @Nonnull final BeanDefinitionBuilder builder) {
- super.doParse(config, parserContext, builder);
-
- if (config.hasAttributeNS(null, NAMESPACE_ATTRIBUTE_NAME)) {
- final String namespace = StringSupport.trimOrNull(config.getAttributeNS(null, NAMESPACE_ATTRIBUTE_NAME));
- builder.addPropertyValue("namespace", namespace);
- }
- }
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2Base64AttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2Base64AttributeEncoderParser.java
index b8ac4fc..8b78057 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2Base64AttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2Base64AttributeEncoderParser.java
@@ -18,54 +18,28 @@
package net.shibboleth.idp.attribute.resolver.spring.enc.impl;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.xml.namespace.QName;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Element;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
-import net.shibboleth.idp.attribute.resolver.spring.enc.BaseAttributeEncoderParser;
+import net.shibboleth.idp.attribute.resolver.spring.enc.BaseSAML2AttributeEncoderParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2ByteAttributeEncoder;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ByteAttributeTranscoder;
/**
- * Spring Bean Definition Parser for {@link SAML2ByteAttributeEncoder}.
+ * Spring Bean Definition Parser for {@link SAML2ByteAttributeTranscoder}.
*/
-public class SAML2Base64AttributeEncoderParser extends BaseAttributeEncoderParser {
+public class SAML2Base64AttributeEncoderParser extends BaseSAML2AttributeEncoderParser {
/** Schema type name.. */
@Nonnull public static final QName TYPE_NAME_RESOLVER = new QName(AttributeResolverNamespaceHandler.NAMESPACE,
"SAML2Base64");
- /** Local name of name format attribute. */
- @Nonnull @NotEmpty public static final String NAME_FORMAT_ATTRIBUTE_NAME = "nameFormat";
-
- /** Local name of friendly name attribute. */
- @Nonnull @NotEmpty public static final String FRIENDLY_NAME_ATTRIBUTE_NAME = "friendlyName";
-
- /** Constructor. */
- public SAML2Base64AttributeEncoderParser() {
- setNameRequired(true);
- }
-
/** {@inheritDoc} */
- @Override protected Class<SAML2ByteAttributeEncoder> getBeanClass(@Nullable final Element element) {
- return SAML2ByteAttributeEncoder.class;
+ @Override
+ protected BeanReference buildTranscoder() {
+ return new RuntimeBeanReference("SAML2ByteTranscoder");
}
- /** {@inheritDoc} */
- @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
- @Nonnull final BeanDefinitionBuilder builder) {
- super.doParse(config, parserContext, builder);
-
- if (config.hasAttributeNS(null, NAME_FORMAT_ATTRIBUTE_NAME)) {
- final String nameFormat = StringSupport.trimOrNull(config.getAttributeNS(null, NAME_FORMAT_ATTRIBUTE_NAME));
- builder.addPropertyValue("nameFormat", nameFormat);
- }
-
- builder.addPropertyValue("friendlyName", config.getAttributeNS(null, FRIENDLY_NAME_ATTRIBUTE_NAME));
- }
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2ScopedStringAttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2ScopedStringAttributeEncoderParser.java
index 8cbb0f6..3c0643a 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2ScopedStringAttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2ScopedStringAttributeEncoderParser.java
@@ -17,62 +17,55 @@
package net.shibboleth.idp.attribute.resolver.spring.enc.impl;
+import java.util.Map;
+
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.xml.namespace.QName;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
-import net.shibboleth.idp.attribute.resolver.spring.enc.BaseScopedAttributeEncoderParser;
+import net.shibboleth.idp.attribute.resolver.spring.enc.BaseSAML2AttributeEncoderParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2ScopedStringAttributeEncoder;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ScopedStringAttributeTranscoder;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
/**
- * Spring Bean Definition Parser for {@link SAML2ScopedStringAttributeEncoder}.
+ * Spring Bean Definition Parser for {@link SAML2ScopedStringAttributeTranscoder}.
*/
-public class SAML2ScopedStringAttributeEncoderParser extends BaseScopedAttributeEncoderParser {
+public class SAML2ScopedStringAttributeEncoderParser extends BaseSAML2AttributeEncoderParser {
/** Schema type name.. */
@Nonnull public static final QName TYPE_NAME_RESOLVER = new QName(AttributeResolverNamespaceHandler.NAMESPACE,
"SAML2ScopedString");
- /** Local name of name format attribute. */
- @Nonnull @NotEmpty public static final String NAME_FORMAT_ATTRIBUTE_NAME = "nameFormat";
-
- /** Local name of friendly name attribute. */
- @Nonnull @NotEmpty public static final String FRIENDLY_NAME_ATTRIBUTE_NAME = "friendlyName";
-
- /** Constructor. */
- public SAML2ScopedStringAttributeEncoderParser() {
- setNameRequired(true);
- }
-
- /** {@inheritDoc} */
- @Override protected Class<SAML2ScopedStringAttributeEncoder> getBeanClass(@Nullable final Element element) {
- return SAML2ScopedStringAttributeEncoder.class;
- }
-
/** {@inheritDoc} */
@Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
- @Nonnull final BeanDefinitionBuilder builder) {
- super.doParse(config, parserContext, builder);
+ @Nonnull final Map<String,Object> rule) {
+ super.doParse(config, parserContext, rule);
- if (config.hasAttributeNS(null, SCOPE_TYPE_ATTRIBUTE_NAME)) {
- builder.addPropertyValue("scopeType",
- StringSupport.trimOrNull(config.getAttributeNS(null, SCOPE_TYPE_ATTRIBUTE_NAME)));
+ if (config.hasAttributeNS(null, "scopeType")) {
+ rule.put(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_TYPE,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "scopeType")));
+ }
+
+ if (config.hasAttributeNS(null, "scopeDelimiter")) {
+ rule.put(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "scopeDelimiter")));
}
- if (config.hasAttributeNS(null, NAME_FORMAT_ATTRIBUTE_NAME)) {
- final String nameFormat = StringSupport.trimOrNull(config.getAttributeNS(null, NAME_FORMAT_ATTRIBUTE_NAME));
- builder.addPropertyValue("nameFormat", nameFormat);
+ if (config.hasAttributeNS(null, "scopeAttribute")) {
+ rule.put(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_ATTR_NAME,
+ StringSupport.trimOrNull(config.getAttributeNS(null, "scopeAttribute")));
}
+ }
- builder.addPropertyValue("friendlyName",
- StringSupport.trimOrNull(config.getAttributeNS(null, FRIENDLY_NAME_ATTRIBUTE_NAME)));
+ /** {@inheritDoc} */
+ @Override
+ protected BeanReference buildTranscoder() {
+ return new RuntimeBeanReference("SAML2ScopedStringTranscoder");
}
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2StringAttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2StringAttributeEncoderParser.java
index 89c64e7..0ae5203 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2StringAttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2StringAttributeEncoderParser.java
@@ -18,55 +18,28 @@
package net.shibboleth.idp.attribute.resolver.spring.enc.impl;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.xml.namespace.QName;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Element;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
-import net.shibboleth.idp.attribute.resolver.spring.enc.BaseAttributeEncoderParser;
+import net.shibboleth.idp.attribute.resolver.spring.enc.BaseSAML2AttributeEncoderParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2StringAttributeEncoder;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2StringAttributeTranscoder;
/**
- * Spring Bean Definition Parser for {@link SAML2StringAttributeEncoder}.
+ * Spring Bean Definition Parser for {@link SAML2StringAttributeTranscoder}.
*/
-public class SAML2StringAttributeEncoderParser extends BaseAttributeEncoderParser {
+public class SAML2StringAttributeEncoderParser extends BaseSAML2AttributeEncoderParser {
/** Schema type name.. */
@Nonnull public static final QName TYPE_NAME_RESOLVER = new QName(AttributeResolverNamespaceHandler.NAMESPACE,
"SAML2String");
-
- /** Local name of name format attribute. */
- @Nonnull @NotEmpty public static final String NAME_FORMAT_ATTRIBUTE_NAME = "nameFormat";
-
- /** Local name of friendly name attribute. */
- @Nonnull @NotEmpty public static final String FRIENDLY_NAME_ATTRIBUTE_NAME = "friendlyName";
-
- /** Constructor. */
- public SAML2StringAttributeEncoderParser() {
- setNameRequired(true);
- }
-
/** {@inheritDoc} */
- @Override protected Class<SAML2StringAttributeEncoder> getBeanClass(@Nullable final Element element) {
- return SAML2StringAttributeEncoder.class;
+ @Override
+ protected BeanReference buildTranscoder() {
+ return new RuntimeBeanReference("SAML2StringTranscoder");
}
- /** {@inheritDoc} */
- @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
- @Nonnull final BeanDefinitionBuilder builder) {
- super.doParse(config, parserContext, builder);
-
- if (config.hasAttributeNS(null, NAME_FORMAT_ATTRIBUTE_NAME)) {
- final String nameFormat = StringSupport.trimOrNull(config.getAttributeNS(null, NAME_FORMAT_ATTRIBUTE_NAME));
- builder.addPropertyValue("nameFormat", nameFormat);
- }
-
- builder.addPropertyValue("friendlyName", config.getAttribute(FRIENDLY_NAME_ATTRIBUTE_NAME));
- }
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2XMLObjectAttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2XMLObjectAttributeEncoderParser.java
index fe21954..2cf1a92 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2XMLObjectAttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/impl/SAML2XMLObjectAttributeEncoderParser.java
@@ -18,53 +18,26 @@
package net.shibboleth.idp.attribute.resolver.spring.enc.impl;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.xml.namespace.QName;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Element;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
-import net.shibboleth.idp.attribute.resolver.spring.enc.BaseAttributeEncoderParser;
+import net.shibboleth.idp.attribute.resolver.spring.enc.BaseSAML2AttributeEncoderParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2XMLObjectAttributeEncoder;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2XMLObjectAttributeTranscoder;
-/** Spring Bean Definition Parser for SAML2 XMLObject attribute encoder. */
-public class SAML2XMLObjectAttributeEncoderParser extends BaseAttributeEncoderParser {
+/** Spring Bean Definition Parser for {@link SAML2XMLObjectAttributeTranscoder}. */
+public class SAML2XMLObjectAttributeEncoderParser extends BaseSAML2AttributeEncoderParser {
/** Schema type name.. */
@Nonnull public static final QName TYPE_NAME_RESOLVER = new QName(AttributeResolverNamespaceHandler.NAMESPACE,
"SAML2XMLObject");
- /** Local name of name format attribute. */
- @Nonnull @NotEmpty public static final String NAME_FORMAT_ATTRIBUTE_NAME = "nameFormat";
-
- /** Local name of friendly name attribute. */
- @Nonnull @NotEmpty public static final String FRIENDLY_NAME_ATTRIBUTE_NAME = "friendlyName";
-
- /** Constructor. */
- public SAML2XMLObjectAttributeEncoderParser() {
- setNameRequired(true);
- }
-
/** {@inheritDoc} */
- @Override protected Class<SAML2XMLObjectAttributeEncoder> getBeanClass(@Nullable final Element element) {
- return SAML2XMLObjectAttributeEncoder.class;
+ @Override
+ protected BeanReference buildTranscoder() {
+ return new RuntimeBeanReference("SAML2XMLObjectTranscoder");
}
- /** {@inheritDoc} */
- @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
- @Nonnull final BeanDefinitionBuilder builder) {
- super.doParse(config, parserContext, builder);
-
- if (config.hasAttributeNS(null, NAME_FORMAT_ATTRIBUTE_NAME)) {
- final String nameFormat = StringSupport.trimOrNull(config.getAttributeNS(null, NAME_FORMAT_ATTRIBUTE_NAME));
- builder.addPropertyValue("nameFormat", nameFormat);
- }
-
- builder.addPropertyValue("friendlyName",
- StringSupport.trimOrNull(config.getAttributeNS(null, FRIENDLY_NAME_ATTRIBUTE_NAME)));
- }
}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverParser.java
index 63b1f09..6e2536d 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverParser.java
@@ -23,26 +23,23 @@ import java.util.Map;
import javax.annotation.Nonnull;
import javax.xml.namespace.QName;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
import net.shibboleth.ext.spring.util.SpringSupport;
import net.shibboleth.idp.attribute.resolver.spring.ad.BaseAttributeDefinitionParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.AbstractDataConnectorParser;
-import net.shibboleth.idp.attribute.resolver.spring.enc.BaseAttributeEncoderParser;
import net.shibboleth.utilities.java.support.xml.ElementSupport;
/**
* Bean definition parser for an {@link net.shibboleth.idp.attribute.resolver.AttributeResolver}. <br/>
*
* There is no bean being summoned up here. Rather we just parse all the children. Then over in the service all the
- * {@link net.shibboleth.idp.attribute.resolver.AttributeDefinition},
- * {@link net.shibboleth.idp.attribute.resolver.DataConnector} and
- * {@link net.shibboleth.idp.saml.attribute.principalconnector.impl.PrincipalConnector} beans are sucked out of Spring
+ * {@link net.shibboleth.idp.attribute.resolver.AttributeDefinition} and
+ * {@link net.shibboleth.idp.attribute.resolver.DataConnector} beans are sucked out of Spring
* by type and injected into a new {@link net.shibboleth.idp.attribute.resolver.impl.AttributeResolverImpl} via a
* {@link net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverServiceStrategy}.
*/
@@ -55,9 +52,6 @@ public class AttributeResolverParser implements BeanDefinitionParser {
/** Schema type. */
@Nonnull public static final QName SCHEMA_TYPE = new QName(AttributeResolverNamespaceHandler.NAMESPACE,
"AttributeResolverType");
-
- /** Log4j logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(BaseAttributeEncoderParser.class);
/**
* {@inheritDoc}
@@ -68,11 +62,17 @@ public class AttributeResolverParser implements BeanDefinitionParser {
List<Element> children;
children = configChildren.get(BaseAttributeDefinitionParser.ELEMENT_NAME);
- SpringSupport.parseCustomElements(children, context);
+ SpringSupport.parseLazyInitCustomElements(children, context);
children = configChildren.get(AbstractDataConnectorParser.ELEMENT_NAME);
- SpringSupport.parseCustomElements(children, context);
+ SpringSupport.parseLazyInitCustomElements(children, context);
+ final NodeList attributeEncoders =
+ config.getElementsByTagNameNS(AttributeResolverNamespaceHandler.NAMESPACE, "AttributeEncoder");
+ for (int i = 0; i < attributeEncoders.getLength(); ++i) {
+ SpringSupport.parseLazyInitCustomElement((Element) attributeEncoders.item(i), context);
+ }
+
return null;
}
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/AttributeRegistryServiceStrategy.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/AttributeRegistryServiceStrategy.java
new file mode 100644
index 0000000..c290c23
--- /dev/null
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/AttributeRegistryServiceStrategy.java
@@ -0,0 +1,100 @@
+/*
+ * 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.idp.attribute.transcoding.spring.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRuleLoader;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.utilities.java.support.service.ServiceException;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
+
+/**
+ * Strategy for summoning up an {@link AttributeTranscoderRegistryImpl} from a populated {@link ApplicationContext}.
+ */
+public class AttributeRegistryServiceStrategy extends AbstractIdentifiableInitializableComponent implements
+ Function<ApplicationContext,ServiceableComponent<AttributeTranscoderRegistry>> {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AttributeRegistryServiceStrategy.class);
+
+ /** Name of bean to supply naming function registry property. */
+ @Nullable @NotEmpty private String namingRegistry;
+
+ /**
+ * Set the name of the bean providing the {@link AttributeTranscoderRegistryImpl#setNamingRegistry()} value.
+ *
+ * @param beanName name of bean of type {@link Map}
+ */
+ public void setNamingRegistry(@Nullable @NotEmpty final String beanName) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ namingRegistry = StringSupport.trimOrNull(beanName);
+ }
+
+ /** {@inheritDoc} */
+ @Nullable public ServiceableComponent<AttributeTranscoderRegistry> apply(
+ @Nullable final ApplicationContext appContext) {
+
+ final Map<Class<?>,Function<?,String>> namingRegistryBean = appContext.getBean(namingRegistry, Map.class);
+
+ final Collection<TranscodingRule> mappingBeans = appContext.getBeansOfType(TranscodingRule.class).values();
+ final Collection<TranscodingRuleLoader> loaderBeans =
+ appContext.getBeansOfType(TranscodingRuleLoader.class).values();
+
+ final Collection<TranscodingRule> holder = new ArrayList<>();
+ if (mappingBeans != null) {
+ holder.addAll(mappingBeans);
+ }
+ if (loaderBeans != null) {
+ loaderBeans.forEach(loader -> holder.addAll(loader.getRules()));
+ }
+
+ final AttributeTranscoderRegistryImpl registry = new AttributeTranscoderRegistryImpl();
+ registry.setId(getId());
+ registry.setApplicationContext(appContext);
+ registry.setNamingRegistry(namingRegistryBean);
+ registry.setTranscoderRegistry(holder);
+
+ try {
+ registry.initialize();
+ } catch (final ComponentInitializationException e) {
+ throw new ServiceException("Unable to initialize attribute transcoder registry for "
+ + appContext.getDisplayName(), e);
+ }
+ return registry;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/package-info.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/package-info.java
similarity index 83%
rename from idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/package-info.java
rename to idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/package-info.java
index 9b82bcc..1278015 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/package-info.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/package-info.java
@@ -16,8 +16,8 @@
*/
/**
- * Classes in this package are to do with the import of attributes
- * as an adjunct to filtering.
+ * For want of a better place. If there are additional classes needed, this
+ * may move to a dedicated module.
*/
-package net.shibboleth.idp.saml.attribute.mapping;
\ No newline at end of file
+package net.shibboleth.idp.attribute.transcoding.spring.impl;
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMapperTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMapperTest.java
index da44ed6..ab688f0 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMapperTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMapperTest.java
@@ -17,9 +17,7 @@
package net.shibboleth.idp.attribute.resolver.spring;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
+import static org.testng.Assert.*;
import java.util.Arrays;
import java.util.Collection;
@@ -27,7 +25,6 @@ import java.util.HashSet;
import org.opensaml.core.OpenSAMLInitBaseTestCase;
import org.opensaml.saml.saml2.core.Attribute;
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
import org.springframework.context.support.ConversionServiceFactoryBean;
import org.springframework.context.support.GenericApplicationContext;
import org.testng.annotations.AfterMethod;
@@ -35,15 +32,13 @@ import org.testng.annotations.Test;
import net.shibboleth.ext.spring.config.StringToDurationConverter;
import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
-import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
+import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.resolver.ResolutionException;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
-import net.shibboleth.idp.saml.attribute.mapping.AttributeMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.RequestedAttributesMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.ScopedStringAttributeValueMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.StringAttributeValueMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.XMLObjectAttributeValueMapper;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ScopedStringAttributeTranscoder;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.service.ReloadableService;
import net.shibboleth.utilities.java.support.service.ServiceException;
@@ -88,33 +83,29 @@ public class AttributeMapperTest extends OpenSAMLInitBaseTestCase {
beanDefinitionReader.loadBeanDefinitions("net/shibboleth/idp/attribute/resolver/spring/mapperTest.xml");
context.refresh();
- final ReloadableService<AttributeResolver> attributeResolverService = context.getBean(ReloadableService.class);
+ final ReloadableService<AttributeTranscoderRegistry> transcoderRegistry = context.getBean(ReloadableService.class);
- attributeResolverService.initialize();
-
- ServiceableComponent<AttributeResolver> serviceableComponent = null;
- RequestedAttributesMapper attributesMapper = null;
+ ServiceableComponent<AttributeTranscoderRegistry> serviceableComponent = null;
try {
- serviceableComponent = attributeResolverService.getServiceableComponent();
-
- attributesMapper = new RequestedAttributesMapper(serviceableComponent.getComponent());
+ serviceableComponent = transcoderRegistry.getServiceableComponent();
+
+ Collection<TranscodingRule> rulesets = serviceableComponent.getComponent().getTranscodingRules(
+ new IdPAttribute("eduPersonScopedAffiliation"), Attribute.class);
+ assertEquals(rulesets.size(), 1);
+ final TranscodingRule rule = rulesets.iterator().next();
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_NAME, String.class), "urn:oid:1.3.6.1.4.1.5923.1.1.1.9");
+ assertNull(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT, String.class));
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME, String.class), "feduPersonScopedAffiliation");
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER, AttributeTranscoder.class) instanceof SAML2ScopedStringAttributeTranscoder);
+ assertEquals(rule.get(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER, String.class), "#");
} finally {
serviceableComponent.unpinComponent();
}
- Collection<AttributeMapper<RequestedAttribute, IdPRequestedAttribute>> mappers = attributesMapper.getMappers();
- assertEquals(mappers.size(), 5);
-
+ /*
for (AttributeMapper<RequestedAttribute, IdPRequestedAttribute> mapper : mappers) {
AbstractSAMLAttributeMapper sMappers = (AbstractSAMLAttributeMapper) mapper;
if (mapper.getId().equals("MapperForfeduPersonScopedAffiliation")) {
- assertEquals(sMappers.getSAMLName(), "urn:oid:1.3.6.1.4.1.5923.1.1.1.9");
- assertEquals(sMappers.getAttributeFormat(), Attribute.URI_REFERENCE);
- assertEquals(sMappers.getAttributeIds().size(), 1);
- assertEquals(sMappers.getAttributeIds().get(0), "eduPersonScopedAffiliation");
- ScopedStringAttributeValueMapper valueMapper =
- (ScopedStringAttributeValueMapper) sMappers.getValueMapper();
- assertEquals(valueMapper.getDelimiter(), "#");
} else if (mapper.getId().equals("MapperForfeduPersonAssurance")) {
assertEquals(sMappers.getSAMLName(), "urn:oid:1.3.6.1.4.1.5923.1.1.1.11");
assertEquals(sMappers.getAttributeFormat(), Attribute.URI_REFERENCE);
@@ -144,5 +135,8 @@ public class AttributeMapperTest extends OpenSAMLInitBaseTestCase {
fail();
}
}
+ */
+
}
-}
+
+}
\ No newline at end of file
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..02df1e3 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: ");
@@ -97,11 +97,12 @@ public class AttributeMappingNodeProcessorTest extends XMLObjectBaseTestCase {
SchemaTypeAwareXMLBeanDefinitionReader beanDefinitionReader =
new SchemaTypeAwareXMLBeanDefinitionReader(context);
- beanDefinitionReader.loadBeanDefinitions("/net/shibboleth/idp/attribute/resolver/filter/service.xml");
+ beanDefinitionReader.loadBeanDefinitions(
+ "/net/shibboleth/idp/attribute/resolver/spring/customBean.xml",
+ "/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 +139,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/java/net/shibboleth/idp/attribute/resolver/spring/BaseAttributeDefinitionParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseAttributeDefinitionParserTest.java
index 082fc1f..0066528 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseAttributeDefinitionParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseAttributeDefinitionParserTest.java
@@ -36,7 +36,6 @@ import net.shibboleth.ext.spring.config.StringToIPRangeConverter;
import net.shibboleth.ext.spring.config.StringToResourceConverter;
import net.shibboleth.ext.spring.context.FilesystemGenericApplicationContext;
import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.resolver.AttributeDefinition;
import net.shibboleth.idp.attribute.resolver.DataConnector;
import net.shibboleth.idp.attribute.resolver.impl.AttributeResolverImpl;
@@ -63,7 +62,7 @@ public abstract class BaseAttributeDefinitionParserTest extends OpenSAMLInitBase
public static final String PRINCIPALCONNECTOR_FILE_PATH = BEAN_FILE_PATH + "pc/";
- private GenericApplicationContext pendingTeardownContext = null;
+ protected GenericApplicationContext pendingTeardownContext = null;
@AfterMethod public void tearDownTestContext() {
if (null == pendingTeardownContext ) {
@@ -178,8 +177,6 @@ public abstract class BaseAttributeDefinitionParserTest extends OpenSAMLInitBase
return getDataConnector(fileName, claz, false);
}
-
-
private <Type extends DataConnector> Type
getDataConnector(final String fileName, final Class<Type> claz, final boolean supressValid) {
@@ -191,23 +188,6 @@ public abstract class BaseAttributeDefinitionParserTest extends OpenSAMLInitBase
return getBean(DATACONNECTOR_FILE_PATH + fileName, claz, context, supressValid);
}
- protected <Type extends AttributeEncoder> Type getAttributeEncoder(final String fileName, final Class<Type> claz) {
-
- final GenericApplicationContext context = new GenericApplicationContext();
- setTestContext(context);
- context.setDisplayName("ApplicationContext: " + claz);
-
- return getAttributeEncoder(fileName, claz, context);
-
- }
-
- protected <Type extends AttributeEncoder> Type getAttributeEncoder(final String fileName, final Class<Type> claz,
- final GenericApplicationContext context) {
-
- return getBean(ENCODER_FILE_PATH + fileName, claz, context);
-
- }
-
static public AttributeResolverImpl getResolver(final ApplicationContext appCtx) {
final AttributeResolverServiceStrategy strategy = new AttributeResolverServiceStrategy();
strategy.setId("testResolver");
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseEncoderDefinitionParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseEncoderDefinitionParserTest.java
new file mode 100644
index 0000000..f6a0437
--- /dev/null
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseEncoderDefinitionParserTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.idp.attribute.resolver.spring;
+
+import static net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder.PROP_ENCODE_TYPE;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.env.MutablePropertySources;
+import org.springframework.core.env.StandardEnvironment;
+import org.springframework.mock.env.MockPropertySource;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+
+/**
+ * Base class for testing Attribute Encoding Parsers
+ */
+public abstract class BaseEncoderDefinitionParserTest extends BaseAttributeDefinitionParserTest {
+
+ protected TranscodingRule getAttributeTranscoderRule(final String fileName) {
+ return getAttributeTranscoderRule(fileName, null, null);
+ }
+
+ protected TranscodingRule getAttributeTranscoderRule(final String fileName,final boolean activation, final Boolean encodeType) {
+ final String encodeTypeString;
+ if (null == encodeType) {
+ encodeTypeString = null;
+ } else if (encodeType ){
+ encodeTypeString = "true";
+ } else {
+ encodeTypeString = "false";
+ }
+ return getAttributeTranscoderRule(fileName, activation?"true":"false", encodeTypeString);
+ }
+
+ private TranscodingRule getAttributeTranscoderRule(final String fileName,
+ final String activationValue,
+ final String encodeType) {
+
+ final GenericApplicationContext context = new GenericApplicationContext();
+
+ final MockPropertySource mockEnvVars = new MockPropertySource();
+ if (activationValue != null) {
+ mockEnvVars.setProperty("the.activation.property", activationValue);
+ }
+ if (encodeType != null) {
+ mockEnvVars.setProperty("the.encodeType.property", encodeType);
+ }
+ mockEnvVars.setProperty("the.empty.property", "");
+ final MutablePropertySources propertySources = context.getEnvironment().getPropertySources();
+ propertySources.replace(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, mockEnvVars);
+
+ return getAttributeTranscoderRule(fileName, context);
+ }
+
+ protected TranscodingRule getAttributeTranscoderRule(final String fileName, final GenericApplicationContext context) {
+
+ setTestContext(context);
+ context.setDisplayName("ApplicationContext for enccoder");
+
+ return getBean(ENCODER_FILE_PATH + fileName, TranscodingRule.class, context);
+
+ }
+
+ static protected void checkEncodeType(final Map<String,Object> rule, boolean expectedValue) {
+ final Object encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.TRUE);
+ if (encodeType instanceof Boolean) {
+ assertTrue(encodeType.equals(expectedValue));
+ } else {
+ assertTrue(expectedValue);
+ }
+ }
+
+ abstract protected void testWithProperties(final boolean activation, final Boolean encodeType);
+
+ @Test public void values() {
+ testWithProperties(true);
+ testWithProperties(false);
+ }
+
+ private void testWithProperties(final boolean activation) {
+ testWithProperties(activation, null);
+ testWithProperties(activation, true);
+ testWithProperties(activation, false);
+ }
+}
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/SimpleAttributeParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/SimpleAttributeParserTest.java
index 2857dd6..4d3c397 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/SimpleAttributeParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/ad/SimpleAttributeParserTest.java
@@ -17,12 +17,9 @@
package net.shibboleth.idp.attribute.resolver.spring.ad;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.*;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -44,8 +41,6 @@ import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParse
import net.shibboleth.idp.attribute.resolver.spring.ad.impl.SimpleAttributeDefinitionParser;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.idp.profile.logic.RelyingPartyIdPredicate;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1StringAttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2StringAttributeEncoder;
import net.shibboleth.idp.saml.impl.TestSources;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
@@ -63,7 +58,8 @@ public class SimpleAttributeParserTest extends BaseAttributeDefinitionParserTest
assertTrue(attrDef.getDisplayDescriptions().isEmpty(), "getDisplayDescriptions().isEmpty()");
assertTrue(attrDef.getDisplayNames().isEmpty(), "getDisplayNames().isEmpty()");
assertEquals(attrDef.getAttributeDependencies().size(), 1);
- assertTrue(attrDef.getAttributeEncoders().isEmpty(), "getgetAttributeEncoders().isEmpty()");
+
+ assertTrue(pendingTeardownContext.getBeansOfType(Collection.class).isEmpty());
}
@Test public void simplePopulated() throws ComponentInitializationException {
@@ -96,13 +92,6 @@ public class SimpleAttributeParserTest extends BaseAttributeDefinitionParserTest
final ResolverDataConnectorDependency dcDep = dcDeps.iterator().next();
assertEquals(dcDep.getDependencyPluginId(), "con1");
assertTrue(dcDep.getAttributeNames().contains("dep1"));
-
- assertEquals(attrDef.getAttributeEncoders().size(), 1);
- final SAML2StringAttributeEncoder e1 =
- (SAML2StringAttributeEncoder) attrDef.getAttributeEncoders().iterator().next();
- assertEquals(e1.getName(), "urn:oid:0.9.2342.19200300.100.1.3");
- assertEquals(e1.getFriendlyName(), "mail");
-
}
@Test public void populated2() throws ComponentInitializationException {
@@ -126,24 +115,6 @@ public class SimpleAttributeParserTest extends BaseAttributeDefinitionParserTest
final Set<ResolverDataConnectorDependency> dcDeps = attrDef.getDataConnectorDependencies();
assertEquals(dcDeps.size(), 0, "getDataConnectorDependencies");
-
-
- assertEquals(attrDef.getAttributeEncoders().size(), 2);
- final List a = new ArrayList(attrDef.getAttributeEncoders());
-
- final SAML2StringAttributeEncoder saml2;
- final SAML1StringAttributeEncoder saml1;
- if (a.get(0) instanceof SAML2StringAttributeEncoder) {
- saml2 = (SAML2StringAttributeEncoder) a.get(0);
- saml1 = (SAML1StringAttributeEncoder) a.get(1);
- } else {
- saml2 = (SAML2StringAttributeEncoder) a.get(1);
- saml1 = (SAML1StringAttributeEncoder) a.get(0);
- }
- assertEquals(saml2.getName(), "urn:oid:0.9.2342.19200300.100.1.3");
- assertEquals(saml2.getFriendlyName(), "mail");
-
- assertEquals(saml1.getName(), "urn:mace:dir:attribute-def:mail");
}
@Test public void bad() throws ComponentInitializationException {
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/Regressions.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/Regressions.java
index a0201e3..136a68b 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/Regressions.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/Regressions.java
@@ -17,19 +17,22 @@
package net.shibboleth.idp.attribute.resolver.spring.enc;
-import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.*;
import java.util.Collection;
+import java.util.Map;
import org.springframework.context.support.GenericApplicationContext;
import org.testng.annotations.Test;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.resolver.AttributeDefinition;
import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2StringAttributeTranscoder;
/**
- *
+ * Test for regressions identified and patched.
*/
public class Regressions extends BaseAttributeDefinitionParserTest {
@@ -39,10 +42,15 @@ public class Regressions extends BaseAttributeDefinitionParserTest {
loadFile(ENCODER_FILE_PATH + "resolver/idp-571.xml", context);
context.refresh();
- Collection<AttributeEncoder> encoders = context.getBeansOfType(AttributeEncoder.class).values();
Collection<AttributeDefinition> definitions = context.getBeansOfType(AttributeDefinition.class).values();
+ Collection<TranscodingRule> transcoderRules = context.getBeansOfType(TranscodingRule.class).values();
- assertEquals(encoders.size(), 1);
assertEquals(definitions.size(), 1);
+ assertEquals(transcoderRules.size(), 1);
+
+ final Map<String,Object> rule = transcoderRules.iterator().next().getMap();
+ assertEquals(rule.get(AttributeTranscoderRegistry.PROP_ID), "skillsoftdept");
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2StringAttributeTranscoder);
}
-}
+
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1Base64AttributeEncoderParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1Base64AttributeEncoderParserTest.java
index 4d0e03a..cacbd1e 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1Base64AttributeEncoderParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1Base64AttributeEncoderParserTest.java
@@ -18,38 +18,52 @@
package net.shibboleth.idp.attribute.resolver.spring.enc;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.function.Predicate;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.testng.annotations.Test;
-import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.attribute.resolver.spring.BaseEncoderDefinitionParserTest;
import net.shibboleth.idp.attribute.resolver.spring.enc.impl.SAML1Base64AttributeEncoderParser;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1ByteAttributeEncoder;
-import net.shibboleth.idp.saml.xml.SAMLConstants;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ByteAttributeTranscoder;
/**
* Test for {@link SAML1Base64AttributeEncoderParser}.
*/
-public class SAML1Base64AttributeEncoderParserTest extends BaseAttributeDefinitionParserTest {
+public class SAML1Base64AttributeEncoderParserTest extends BaseEncoderDefinitionParserTest {
- @Test public void resolver() {
- final SAML1ByteAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml1Base64.xml", SAML1ByteAttributeEncoder.class);
+ protected void testWithProperties(final boolean activation, final Boolean encodeType) {
+
+ final Map<String,Object> rule =
+ getAttributeTranscoderRule("resolver/saml1Base64.xml", activation, encodeType).getMap();
- assertEquals(encoder.getName(), "SAML1_BASE64_ATTRIBUTE_NAME");
- assertEquals(encoder.getNamespace(),"SAML1_BASE64_ATTRIBUTE_NAME_SPACE");
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML1ByteAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "SAML1_BASE64_ATTRIBUTE_NAME");
+ assertEquals(rule.get(SAML1AttributeTranscoder.PROP_NAMESPACE), "SAML1_BASE64_ATTRIBUTE_NAME_SPACE");
+ assertEquals(activation, ((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, encodeType==null ? false: encodeType);
}
@Test public void defaultCase() {
- final SAML1ByteAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml1Base64Default.xml", SAML1ByteAttributeEncoder.class);
+ final Map<String,Object> rule = getAttributeTranscoderRule("resolver/saml1Base64Default.xml").getMap();
- assertEquals(encoder.getName(), "Base64_ATTRIBUTE");
- assertEquals(encoder.getNamespace(), SAMLConstants.SAML1_ATTR_NAMESPACE_URI);
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML1ByteAttributeTranscoder);
+ assertEquals(rule.get(SAML1AttributeTranscoder.PROP_NAME), "Base64_ATTRIBUTE");
+ assertNull(rule.get(SAML1AttributeTranscoder.PROP_NAMESPACE));
+ assertFalse(((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test(expectedExceptions={BeanDefinitionStoreException.class,}) public void noName() {
- getAttributeEncoder("resolver/saml1Base64NoName.xml", SAML1ByteAttributeEncoder.class);
+ getAttributeTranscoderRule("resolver/saml1Base64NoName.xml");
}
}
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1ScopedStringAttributeEncoderParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1ScopedStringAttributeEncoderParserTest.java
index b31b7ed..cbbcb5a 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1ScopedStringAttributeEncoderParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1ScopedStringAttributeEncoderParserTest.java
@@ -18,44 +18,59 @@
package net.shibboleth.idp.attribute.resolver.spring.enc;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.function.Predicate;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.testng.annotations.Test;
-import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.attribute.resolver.spring.BaseEncoderDefinitionParserTest;
import net.shibboleth.idp.attribute.resolver.spring.enc.impl.SAML1ScopedStringAttributeEncoderParser;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1ScopedStringAttributeEncoder;
-import net.shibboleth.idp.saml.xml.SAMLConstants;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ScopedStringAttributeTranscoder;
/**
* Test for {@link SAML1ScopedStringAttributeEncoderParser}.
*/
-public class SAML1ScopedStringAttributeEncoderParserTest extends BaseAttributeDefinitionParserTest {
+public class SAML1ScopedStringAttributeEncoderParserTest extends BaseEncoderDefinitionParserTest {
- @Test public void resolver() {
- final SAML1ScopedStringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml1Scoped.xml", SAML1ScopedStringAttributeEncoder.class);
+ protected void testWithProperties(final boolean activation, final Boolean encodeType) {
+
+ final Map<String,Object> rule =
+ getAttributeTranscoderRule("resolver/saml1Scoped.xml", activation, encodeType).getMap();
- assertEquals(encoder.getName(), "SAML1_SCOPED_ATTRIBUTE_NAME");
- assertEquals(encoder.getNamespace(),"SAML1_SCOPED_ATTRIBUTE_NAME_FORMAT");
- assertEquals(encoder.getScopeType(),"attribute");
- assertEquals(encoder.getScopeAttributeName(),"saml1ScopeAttrib");
- assertEquals(encoder.getScopeDelimiter(),"#@#");
- }
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML1ScopedStringAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "SAML1_SCOPED_ATTRIBUTE_NAME");
+ assertEquals(rule.get(SAML1AttributeTranscoder.PROP_NAMESPACE), "SAML1_SCOPED_ATTRIBUTE_NAME_FORMAT");
+ assertEquals(rule.get(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_TYPE), "attribute");
+ assertEquals(rule.get(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_ATTR_NAME), "saml1ScopeAttrib");
+ assertEquals(rule.get(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER), "#@#");
+ assertEquals(activation, ((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, encodeType!=null ? encodeType : false);
+}
@Test public void defaultCase() {
- final SAML1ScopedStringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml1ScopedDefault.xml", SAML1ScopedStringAttributeEncoder.class);
-
- assertEquals(encoder.getName(), "saml1_scoped_name");
- assertEquals(encoder.getNamespace(), SAMLConstants.SAML1_ATTR_NAMESPACE_URI);
- assertEquals(encoder.getScopeType(),"attribute");
- assertEquals(encoder.getScopeDelimiter(),"@");
- assertEquals(encoder.getScopeAttributeName(),"Scope");
+ final Map<String,Object> rule = getAttributeTranscoderRule("resolver/saml1ScopedDefault.xml").getMap();
+
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML1ScopedStringAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "saml1_scoped_name");
+ assertNull(rule.get(SAML1AttributeTranscoder.PROP_NAMESPACE));
+ assertNull(rule.get(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_TYPE));
+ assertNull(rule.get(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_ATTR_NAME));
+ assertNull(rule.get(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER));
+ assertFalse(((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test(expectedExceptions={BeanDefinitionStoreException.class,}) public void noName() {
- getAttributeEncoder("resolver/saml1ScopedNoName.xml", SAML1ScopedStringAttributeEncoder.class);
+ getAttributeTranscoderRule("resolver/saml1ScopedNoName.xml");
}
-}
+
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1StringAttributeEncoderParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1StringAttributeEncoderParserTest.java
index 9cd4a60..ee124ba 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1StringAttributeEncoderParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1StringAttributeEncoderParserTest.java
@@ -18,38 +18,53 @@
package net.shibboleth.idp.attribute.resolver.spring.enc;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.function.Predicate;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.testng.annotations.Test;
-import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.attribute.resolver.spring.BaseEncoderDefinitionParserTest;
import net.shibboleth.idp.attribute.resolver.spring.enc.impl.SAML1StringAttributeEncoderParser;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1StringAttributeEncoder;
-import net.shibboleth.idp.saml.xml.SAMLConstants;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1StringAttributeTranscoder;
/**
* Test for {@link SAML1StringAttributeEncoderParser}.
*/
-public class SAML1StringAttributeEncoderParserTest extends BaseAttributeDefinitionParserTest {
+public class SAML1StringAttributeEncoderParserTest extends BaseEncoderDefinitionParserTest {
- @Test public void newNameSpace() {
- final SAML1StringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml1String.xml", SAML1StringAttributeEncoder.class);
+ protected void testWithProperties(final boolean activation, final Boolean encodeType) {
+
+ final Map<String,Object> rule =
+ getAttributeTranscoderRule("resolver/saml1String.xml", activation, encodeType).getMap();
- assertEquals(encoder.getName(), "SAML1_STRING_ATTRIBUTE_NAME");
- assertEquals(encoder.getNamespace(),"SAML1_STRING_ATTRIBUTE_NAME_SPACE");
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML1StringAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "SAML1_STRING_ATTRIBUTE_NAME");
+ assertEquals(rule.get(SAML1AttributeTranscoder.PROP_NAMESPACE), "SAML1_STRING_ATTRIBUTE_NAME_SPACE");
+ assertEquals(activation, ((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test public void defaultCase() {
- final SAML1StringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml1StringDefault.xml", SAML1StringAttributeEncoder.class);
+ final Map<String,Object> rule = getAttributeTranscoderRule("resolver/saml1StringDefault.xml").getMap();
- assertEquals(encoder.getName(), "ATTRIBUTE");
- assertEquals(encoder.getNamespace(), SAMLConstants.SAML1_ATTR_NAMESPACE_URI);
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML1StringAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "ATTRIBUTE");
+ assertNull(rule.get(SAML1AttributeTranscoder.PROP_NAMESPACE));
+ assertFalse(((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test(expectedExceptions={BeanDefinitionStoreException.class,}) public void noName() {
- getAttributeEncoder("resolver/saml1StringNoName.xml", SAML1StringAttributeEncoder.class);
+ getAttributeTranscoderRule("resolver/saml1StringNoName.xml");
}
-}
+
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1XMLObjectAttributeEncoderParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1XMLObjectAttributeEncoderParserTest.java
index ccda6b2..7f9f62a 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1XMLObjectAttributeEncoderParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML1XMLObjectAttributeEncoderParserTest.java
@@ -18,37 +18,51 @@
package net.shibboleth.idp.attribute.resolver.spring.enc;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.function.Predicate;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.testng.annotations.Test;
-import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.attribute.resolver.spring.BaseEncoderDefinitionParserTest;
import net.shibboleth.idp.attribute.resolver.spring.enc.impl.SAML1XMLObjectAttributeEncoderParser;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1XMLObjectAttributeEncoder;
-import net.shibboleth.idp.saml.xml.SAMLConstants;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1XMLObjectAttributeTranscoder;
/**
* Test for {@link SAML1XMLObjectAttributeEncoderParser}.
*/
-public class SAML1XMLObjectAttributeEncoderParserTest extends BaseAttributeDefinitionParserTest {
+public class SAML1XMLObjectAttributeEncoderParserTest extends BaseEncoderDefinitionParserTest {
- @Test public void resolver() {
- final SAML1XMLObjectAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml1XmlObject.xml", SAML1XMLObjectAttributeEncoder.class);
+ protected void testWithProperties(final boolean activation, final Boolean encodeType) {
+
+ final Map<String,Object> rule =
+ getAttributeTranscoderRule("resolver/saml1XmlObject.xml", activation, encodeType).getMap();
- assertEquals(encoder.getName(), "SAML1_XMLObject_ATTRIBUTE_NAME");
- assertEquals(encoder.getNamespace(),"SAML1_XMLObject_ATTRIBUTE_NAME_SPACE");
- }
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML1XMLObjectAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "SAML1_XMLObject_ATTRIBUTE_NAME");
+ assertEquals(rule.get(SAML1AttributeTranscoder.PROP_NAMESPACE), "SAML1_XMLObject_ATTRIBUTE_NAME_SPACE");
+ assertEquals(activation, ((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, encodeType!=null ? encodeType : true);
+}
@Test public void defaultCase() {
- final SAML1XMLObjectAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml1XmlObjectDefault.xml", SAML1XMLObjectAttributeEncoder.class);
+ final Map<String,Object> rule = getAttributeTranscoderRule("resolver/saml1XmlObjectDefault.xml").getMap();
- assertEquals(encoder.getName(), "XMLObject_ATTRIBUTE");
- assertEquals(encoder.getNamespace(), SAMLConstants.SAML1_ATTR_NAMESPACE_URI);
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML1XMLObjectAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "XMLObject_ATTRIBUTE");
+ assertNull(rule.get(SAML1AttributeTranscoder.PROP_NAMESPACE));
+ assertFalse(((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test(expectedExceptions={BeanDefinitionStoreException.class,}) public void noName() {
- getAttributeEncoder("resolver/saml1XmlObjectNoName.xml", SAML1XMLObjectAttributeEncoder.class);
+ getAttributeTranscoderRule("resolver/saml1XmlObjectNoName.xml");
}
}
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2Base64AttributeEncoderParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2Base64AttributeEncoderParserTest.java
index bef5195..17c6e54 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2Base64AttributeEncoderParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2Base64AttributeEncoderParserTest.java
@@ -18,40 +18,53 @@
package net.shibboleth.idp.attribute.resolver.spring.enc;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.function.Predicate;
-import org.opensaml.saml.saml2.core.Attribute;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.testng.annotations.Test;
-import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.attribute.resolver.spring.BaseEncoderDefinitionParserTest;
import net.shibboleth.idp.attribute.resolver.spring.enc.impl.SAML2Base64AttributeEncoderParser;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2ByteAttributeEncoder;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ByteAttributeTranscoder;
/**
* Test for {@link SAML2Base64AttributeEncoderParser}.
*/
-public class SAML2Base64AttributeEncoderParserTest extends BaseAttributeDefinitionParserTest {
+public class SAML2Base64AttributeEncoderParserTest extends BaseEncoderDefinitionParserTest {
- @Test public void resolver() {
- final SAML2ByteAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2Base64.xml", SAML2ByteAttributeEncoder.class);
+ protected void testWithProperties(final boolean activation, final Boolean encodeType) {
+
+ final Map<String,Object> rule =
+ getAttributeTranscoderRule("resolver/saml2Base64.xml", activation, encodeType).getMap();
- assertEquals(encoder.getName(), "Saml2Base64_ATTRIBUTE_NAME");
- assertEquals(encoder.getFriendlyName(),"Saml2Base64_ATTRIBUTE_FRIENDLY_NAME");
- assertEquals(encoder.getNameFormat(),"Saml2Base64_ATTRIBUTE_NAME_FORMAT");
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2ByteAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "Saml2Base64_ATTRIBUTE_NAME");
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT), "Saml2Base64_ATTRIBUTE_NAME_FORMAT");
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME), "Saml2Base64_ATTRIBUTE_FRIENDLY_NAME");
+ assertEquals(activation, ((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test public void defaultCase() {
- final SAML2ByteAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2Base64Default.xml", SAML2ByteAttributeEncoder.class);
+ final Map<String,Object> rule = getAttributeTranscoderRule("resolver/saml2Base64Default.xml").getMap();
- assertEquals(encoder.getName(), "Base64Name");
- assertNull(encoder.getFriendlyName());
- assertEquals(encoder.getNameFormat(), Attribute.URI_REFERENCE);
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2ByteAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "Base64Name");
+ assertNull(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT));
+ assertNull(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME));
+ assertFalse(((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test(expectedExceptions={BeanDefinitionStoreException.class,}) public void noName() {
- getAttributeEncoder("resolver/saml2Base64NoName.xml", SAML2ByteAttributeEncoder.class);
+ getAttributeTranscoderRule("resolver/saml2Base64NoName.xml");
}
}
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2ScopedStringAttributeEncoderParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2ScopedStringAttributeEncoderParserTest.java
index 0dcabfa..1741af2 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2ScopedStringAttributeEncoderParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2ScopedStringAttributeEncoderParserTest.java
@@ -18,46 +18,59 @@
package net.shibboleth.idp.attribute.resolver.spring.enc;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.function.Predicate;
-import org.opensaml.saml.saml2.core.Attribute;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.testng.annotations.Test;
-import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.attribute.resolver.spring.BaseEncoderDefinitionParserTest;
import net.shibboleth.idp.attribute.resolver.spring.enc.impl.SAML2ScopedStringAttributeEncoderParser;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2ScopedStringAttributeEncoder;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ScopedStringAttributeTranscoder;
/**
* Test for {@link SAML2ScopedStringAttributeEncoderParser}.
*/
-public class SAML2ScopedStringAttributeEncoderParserTest extends BaseAttributeDefinitionParserTest {
-
- @Test public void resolver() {
- final SAML2ScopedStringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2Scoped.xml", SAML2ScopedStringAttributeEncoder.class);
-
- assertEquals(encoder.getName(), "ATTRIBUTE_NAME");
- assertEquals(encoder.getFriendlyName(),"ATTRIBUTE_FRIENDLY_NAME");
- assertEquals(encoder.getNameFormat(),"ATTRIBUTE_NAME_FORMAT");
- assertEquals(encoder.getScopeType(),"attribute");
- assertEquals(encoder.getScopeAttributeName(),"scopeAttrib");
- assertEquals(encoder.getScopeDelimiter(),"###");
+public class SAML2ScopedStringAttributeEncoderParserTest extends BaseEncoderDefinitionParserTest {
+
+ protected void testWithProperties(final boolean activation, final Boolean encodeType) {
+
+ final Map<String,Object> rule =
+ getAttributeTranscoderRule("resolver/saml2Scoped.xml", activation, encodeType).getMap();
+
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2ScopedStringAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "ATTRIBUTE_NAME");
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT), "ATTRIBUTE_NAME_FORMAT");
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME), "ATTRIBUTE_FRIENDLY_NAME");
+ assertEquals(rule.get(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_TYPE), "attribute");
+ assertEquals(rule.get(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_ATTR_NAME), "scopeAttrib");
+ assertEquals(rule.get(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER), "###");
+ assertEquals(activation, ((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, encodeType!=null ? encodeType : false);
}
@Test public void defaultCase() {
- final SAML2ScopedStringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2ScopedDefault.xml", SAML2ScopedStringAttributeEncoder.class);
-
- assertEquals(encoder.getName(), "name");
- assertNull(encoder.getFriendlyName());
- assertEquals(encoder.getNameFormat(), Attribute.URI_REFERENCE);
- assertEquals(encoder.getScopeType(),"inline");
- assertEquals(encoder.getScopeDelimiter(),"@");
- assertEquals(encoder.getScopeAttributeName(),"Scope");
+ final Map<String,Object> rule = getAttributeTranscoderRule("resolver/saml2ScopedDefault.xml").getMap();
+
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2ScopedStringAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "name");
+ assertNull(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT));
+ assertNull(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME));
+ assertNull(rule.get(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_TYPE));
+ assertNull(rule.get(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_ATTR_NAME));
+ assertNull(rule.get(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER));
+ assertFalse(((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test(expectedExceptions={BeanDefinitionStoreException.class,}) public void noName() {
- getAttributeEncoder("resolver/saml2ScopedNoName.xml", SAML2ScopedStringAttributeEncoder.class);
+ getAttributeTranscoderRule("resolver/saml2ScopedNoName.xml");
}
}
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2StringAttributeEncoderParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2StringAttributeEncoderParserTest.java
index 0961d4e..67cb02c 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2StringAttributeEncoderParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2StringAttributeEncoderParserTest.java
@@ -20,72 +20,52 @@ package net.shibboleth.idp.attribute.resolver.spring.enc;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
-import org.opensaml.saml.saml2.core.Attribute;
+import java.util.Map;
+import java.util.function.Predicate;
+
import org.springframework.beans.factory.BeanDefinitionStoreException;
-import org.springframework.context.support.GenericApplicationContext;
import org.testng.annotations.Test;
-import com.google.common.base.Predicates;
-
-import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.attribute.resolver.spring.BaseEncoderDefinitionParserTest;
import net.shibboleth.idp.attribute.resolver.spring.enc.impl.SAML2StringAttributeEncoderParser;
-import net.shibboleth.idp.profile.logic.ScriptedPredicate;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2StringAttributeEncoder;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2StringAttributeTranscoder;
/**
* Test for {@link SAML2StringAttributeEncoderParser}.
*/
-public class SAML2StringAttributeEncoderParserTest extends BaseAttributeDefinitionParserTest {
+public class SAML2StringAttributeEncoderParserTest extends BaseEncoderDefinitionParserTest {
- @Test public void resolver() {
- final SAML2StringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2String.xml", SAML2StringAttributeEncoder.class);
+ protected void testWithProperties(final boolean activation, final Boolean encodeType) {
+
+ final Map<String,Object> rule =
+ getAttributeTranscoderRule("resolver/saml2String.xml", activation, encodeType).getMap();
- assertEquals(encoder.getName(), "Saml2String_ATTRIBUTE_NAME");
- assertEquals(encoder.getFriendlyName(),"Saml2String_ATTRIBUTE_FRIENDLY_NAME");
- assertEquals(encoder.getNameFormat(),"Saml2String_ATTRIBUTE_NAME_FORMAT");
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2StringAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "Saml2String_ATTRIBUTE_NAME");
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT), "Saml2String_ATTRIBUTE_NAME_FORMAT");
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME), "Saml2String_ATTRIBUTE_FRIENDLY_NAME");
+ assertEquals(activation, ((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, encodeType!=null ? encodeType : false);
}
@Test public void defaultCase() {
- final SAML2StringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2StringDefault.xml", SAML2StringAttributeEncoder.class);
+ final Map<String,Object> rule = getAttributeTranscoderRule("resolver/saml2StringDefault.xml").getMap();
- assertSame(encoder.getActivationCondition(), Predicates.alwaysTrue());
- assertTrue(encoder.getActivationCondition().test(null));
- assertEquals(encoder.getName(), "Saml2StringName");
- assertNull(encoder.getFriendlyName());
- assertEquals(encoder.getNameFormat(), Attribute.URI_REFERENCE);
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2StringAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "Saml2StringName");
+ assertNull(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT));
+ assertNull(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME));
+ assertFalse(((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test(expectedExceptions={BeanDefinitionStoreException.class,}) public void noName() {
- getAttributeEncoder("resolver/saml2StringNoName.xml", SAML2StringAttributeEncoder.class);
+ getAttributeTranscoderRule("resolver/saml2StringNoName.xml");
}
- @Test public void conditional() {
- final GenericApplicationContext context = new GenericApplicationContext();
- setTestContext(context);
-
- loadFile(ENCODER_FILE_PATH + "predicates.xml", context);
-
- final SAML2StringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2StringConditional.xml", SAML2StringAttributeEncoder.class, context);
-
- assertSame(encoder.getActivationCondition(), Predicates.alwaysFalse());
- assertFalse(encoder.getActivationCondition().test(null));
- }
-
- @Test public void conditionalScript() {
- final GenericApplicationContext context = new GenericApplicationContext();
- setTestContext(context);
-
- final SAML2StringAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2String.xml", SAML2StringAttributeEncoder.class, context);
-
- assertTrue(encoder.getActivationCondition() instanceof ScriptedPredicate);
- assertFalse(encoder.getActivationCondition().test(null));
- }
-
-}
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2XMLObjectAttributeEncoderParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2XMLObjectAttributeEncoderParserTest.java
index a74e957..513cc6a 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2XMLObjectAttributeEncoderParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/SAML2XMLObjectAttributeEncoderParserTest.java
@@ -18,40 +18,54 @@
package net.shibboleth.idp.attribute.resolver.spring.enc;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.function.Predicate;
-import org.opensaml.saml.saml2.core.Attribute;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.testng.annotations.Test;
-import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
+import net.shibboleth.idp.attribute.resolver.spring.BaseEncoderDefinitionParserTest;
import net.shibboleth.idp.attribute.resolver.spring.enc.impl.SAML2XMLObjectAttributeEncoderParser;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2XMLObjectAttributeEncoder;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2XMLObjectAttributeTranscoder;
/**
* Test for {@link SAML2XMLObjectAttributeEncoderParser}.
*/
-public class SAML2XMLObjectAttributeEncoderParserTest extends BaseAttributeDefinitionParserTest {
+public class SAML2XMLObjectAttributeEncoderParserTest extends BaseEncoderDefinitionParserTest {
- @Test public void resolver() {
- final SAML2XMLObjectAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2XmlObject.xml", SAML2XMLObjectAttributeEncoder.class);
+ protected void testWithProperties(final boolean activation, final Boolean encodeType) {
+
+ final Map<String,Object> rule =
+ getAttributeTranscoderRule("resolver/saml2XmlObject.xml", activation, encodeType).getMap();
- assertEquals(encoder.getName(), "Saml2XmlObject_ATTRIBUTE_NAME");
- assertEquals(encoder.getFriendlyName(),"Saml2XmlObject_ATTRIBUTE_FRIENDLY_NAME");
- assertEquals(encoder.getNameFormat(),"Saml2XmlObject_ATTRIBUTE_NAME_FORMAT");
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2XMLObjectAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "Saml2XmlObject_ATTRIBUTE_NAME");
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT), "Saml2XmlObject_ATTRIBUTE_NAME_FORMAT");
+ assertEquals(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME), "Saml2XmlObject_ATTRIBUTE_FRIENDLY_NAME");
+ assertEquals(activation, ((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, encodeType!=null ? encodeType : true);
}
@Test public void defaultCase() {
- final SAML2XMLObjectAttributeEncoder encoder =
- getAttributeEncoder("resolver/saml2XmlObjectDefault.xml", SAML2XMLObjectAttributeEncoder.class);
+ final Map<String,Object> rule = getAttributeTranscoderRule("resolver/saml2XmlObjectDefault.xml").getMap();
- assertEquals(encoder.getName(), "XmlObjectName");
- assertNull(encoder.getFriendlyName());
- assertEquals(encoder.getNameFormat(), Attribute.URI_REFERENCE);
+ assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2XMLObjectAttributeTranscoder);
+ assertEquals(rule.get(SAMLAttributeTranscoder.PROP_NAME), "XmlObjectName");
+ assertNull(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT));
+ assertNull(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME));
+ assertFalse(((Predicate) rule.get(AttributeTranscoderRegistry.PROP_CONDITION)).test(null));
+ checkEncodeType(rule, true);
}
@Test(expectedExceptions={BeanDefinitionStoreException.class,}) public void noName() {
- getAttributeEncoder("resolver/saml2XmlObjectNoName.xml", SAML2XMLObjectAttributeEncoder.class);
+ getAttributeTranscoderRule("resolver/saml2XmlObjectNoName.xml");
}
-}
+
+}
\ No newline at end of file
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..957ac48 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,37 +5,47 @@
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>
- <value>/net/shibboleth/idp/attribute/resolver/filter/resolver.xml
- </value>
+ <value>/net/shibboleth/idp/attribute/resolver/filter/resolver.xml</value>
</util:list>
</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-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml
index ef730da..19a1bb3 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml
@@ -10,17 +10,41 @@
default-init-method="initialize"
default-destroy-method="destroy">
+
<util:map id="shibboleth.CustomScriptObject">
<entry key="foo" value="bar"/>
- </util:map>
+ </util:map>
+
<util:map id="other.CustomScriptObject">
<entry key="bar" value="foo"/>
- </util:map>
+ </util:map>
+
+ <bean id="shibboleth.Predicate" class="com.google.common.base.Predicates" factory-method="alwaysFalse"/>
<bean id="shibboleth.PropertySourcesPlaceholderConfigurer"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"
p:placeholderPrefix="%{" p:placeholderSuffix="}" />
+ <!-- Necessary for encoder parsing to function, normally part of registry wiring. -->
+
+ <bean id="SAML2StringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2StringAttributeTranscoder" />
+ <bean id="SAML2ScopedStringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ScopedStringAttributeTranscoder" />
+ <bean id="SAML2ByteTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ByteAttributeTranscoder" />
+ <bean id="SAML2XMLObjectTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2XMLObjectAttributeTranscoder" />
+
+ <bean id="SAML1StringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1StringAttributeTranscoder" />
+ <bean id="SAML1ScopedStringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ScopedStringAttributeTranscoder" />
+ <bean id="SAML1ByteTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ByteAttributeTranscoder" />
+ <bean id="SAML1XMLObjectTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1XMLObjectAttributeTranscoder" />
+
</beans>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/predicates.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/predicates.xml
deleted file mode 100644
index 8b4b613..0000000
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/predicates.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:c="http://www.springframework.org/schema/c" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
-
- <bean id="predicate" class="com.google.common.base.Predicates" factory-method="alwaysFalse"/>
-</beans>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/idp-571.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/idp-571.xml
index 81ca522..304812b 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/idp-571.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/idp-571.xml
@@ -8,13 +8,10 @@
<AttributeEncoder xsi:type="SAML2String" name="skillsoftdept" friendlyName="dept name for skillsoft" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified" />
<Script><![CDATA[
-
importPackage(Packages.edu.internet2.middleware.shibboleth.common.attribute.provider);
// Create attribute to be returned from definition
skillsoftdept = new BasicAttribute("skillsoftdept");
-
-
]]></Script>
</AttributeDefinition>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Base64.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Base64.xml
index d41c048..389ee75 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Base64.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Base64.xml
@@ -4,6 +4,11 @@
xmlns="urn:mace:shibboleth:2.0:resolver"
name="SAML1_BASE64_ATTRIBUTE_NAME"
namespace="SAML1_BASE64_ATTRIBUTE_NAME_SPACE"
- xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
-/>
-
\ No newline at end of file
+ encodeType="%{the.encodeType.property:false}"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <ActivationConditionScript>
+ <Script>%{the.activation.property}</Script>
+ </ActivationConditionScript>
+
+</AttributeEncoder>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Base64Default.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Base64Default.xml
index 972e98b..20b8a07 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Base64Default.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Base64Default.xml
@@ -1,4 +1,6 @@
<AttributeEncoder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mace:shibboleth:2.0:resolver"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
- xsi:type="SAML1Base64" name="Base64_ATTRIBUTE"/>
+ xsi:type="SAML1Base64"
+ name="Base64_ATTRIBUTE"
+ activationConditionRef="shibboleth.Predicate"/>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Scoped.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Scoped.xml
index 0e73efd..43beb17 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Scoped.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1Scoped.xml
@@ -7,5 +7,12 @@
scopeType="attribute"
scopeAttribute="saml1ScopeAttrib"
scopeDelimiter="#@#"
- xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"/>
+ encodeType="%{the.encodeType.property:false}"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <ActivationConditionScript>
+ <Script>%{the.activation.property}</Script>
+ </ActivationConditionScript>
+
+</AttributeEncoder>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1ScopedDefault.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1ScopedDefault.xml
index 39f4943..13366a5 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1ScopedDefault.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1ScopedDefault.xml
@@ -1,5 +1,6 @@
<AttributeEncoder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mace:shibboleth:2.0:resolver"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
xsi:type="SAML1ScopedString"
- name="saml1_scoped_name" />
+ name="saml1_scoped_name"
+ activationConditionRef="shibboleth.Predicate"/>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1String.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1String.xml
index c78ae5b..2f07950 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1String.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1String.xml
@@ -4,6 +4,11 @@
xmlns="urn:mace:shibboleth:2.0:resolver"
name="SAML1_STRING_ATTRIBUTE_NAME"
namespace="SAML1_STRING_ATTRIBUTE_NAME_SPACE"
- xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
-/>
-
\ No newline at end of file
+ encodeType="%{the.empty.property}"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <ActivationConditionScript>
+ <Script>%{the.activation.property}</Script>
+ </ActivationConditionScript>
+
+</AttributeEncoder>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1StringDefault.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1StringDefault.xml
index dfae337..d351751 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1StringDefault.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1StringDefault.xml
@@ -1,5 +1,6 @@
<AttributeEncoder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mace:shibboleth:2.0:resolver"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
xsi:type="SAML1String"
- name="ATTRIBUTE"/>
+ name="ATTRIBUTE"
+ activationConditionRef="shibboleth.Predicate"/>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1XmlObject.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1XmlObject.xml
index baa15a5..8ad6608 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1XmlObject.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1XmlObject.xml
@@ -4,6 +4,11 @@
xmlns="urn:mace:shibboleth:2.0:resolver"
name="SAML1_XMLObject_ATTRIBUTE_NAME"
namespace="SAML1_XMLObject_ATTRIBUTE_NAME_SPACE"
- xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
-/>
-
\ No newline at end of file
+ encodeType="%{the.encodeType.property:true}"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <ActivationConditionScript>
+ <Script>%{the.activation.property}</Script>
+ </ActivationConditionScript>
+
+</AttributeEncoder>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1XmlObjectDefault.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1XmlObjectDefault.xml
index 7da2157..ded115f 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1XmlObjectDefault.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml1XmlObjectDefault.xml
@@ -3,5 +3,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mace:shibboleth:2.0:resolver"
name="XMLObject_ATTRIBUTE"
+ activationConditionRef="shibboleth.Predicate"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"/>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Base64.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Base64.xml
index 3681d25..bf07b56 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Base64.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Base64.xml
@@ -5,5 +5,11 @@
name="Saml2Base64_ATTRIBUTE_NAME"
nameFormat="Saml2Base64_ATTRIBUTE_NAME_FORMAT"
friendlyName="Saml2Base64_ATTRIBUTE_FRIENDLY_NAME"
- xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"
-/>
\ No newline at end of file
+ encodeType="%{the.empty.property}"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <ActivationConditionScript>
+ <Script>%{the.activation.property}</Script>
+ </ActivationConditionScript>
+
+</AttributeEncoder>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Base64Default.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Base64Default.xml
index 430b049..a0d61fc 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Base64Default.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Base64Default.xml
@@ -3,5 +3,6 @@
xsi:type="SAML2Base64"
xmlns="urn:mace:shibboleth:2.0:resolver"
name="Base64Name"
+ activationConditionRef="shibboleth.Predicate"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"/>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Scoped.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Scoped.xml
index 4b01de5..8b9c3ae 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Scoped.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2Scoped.xml
@@ -8,5 +8,11 @@
scopeType="attribute"
scopeAttribute="scopeAttrib"
scopeDelimiter="###"
- xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd" />
-
\ No newline at end of file
+ encodeType="%{the.encodeType.property:false}"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <ActivationConditionScript>
+ <Script>%{the.activation.property}</Script>
+ </ActivationConditionScript>
+
+</AttributeEncoder>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2ScopedDefault.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2ScopedDefault.xml
index 7f0778b..a44248a 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2ScopedDefault.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2ScopedDefault.xml
@@ -3,5 +3,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mace:shibboleth:2.0:resolver"
name="name"
+ activationConditionRef="shibboleth.Predicate"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"/>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2ScopedNoName.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2ScopedNoName.xml
index d2a50c0..c6222ea 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2ScopedNoName.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2ScopedNoName.xml
@@ -1,13 +1,8 @@
-<resolver:AttributeEncoder
+<AttributeEncoder
xsi:type="enc:SAML2ScopedString"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:enc="urn:mace:shibboleth:2.0:attribute:encoder"
- xmlns:resolver="urn:mace:shibboleth:2.0:resolver"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="urn:mace:shibboleth:2.0:attribute:encoder"
+ xmlns="urn:mace:shibboleth:2.0:resolver"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd
- urn:mace:shibboleth:2.0:resolver:pc http://shibboleth.net/schema/idp/shibboleth-attribute-resolver-pc.xsd
- urn:mace:shibboleth:2.0:resolver:ad http://shibboleth.net/schema/idp/shibboleth-attribute-resolver-ad.xsd
- urn:mace:shibboleth:2.0:resolver:dc http://shibboleth.net/schema/idp/shibboleth-attribute-resolver-dc.xsd
- urn:mace:shibboleth:2.0:attribute:encoder http://shibboleth.net/schema/idp/shibboleth-attribute-encoder.xsd
- urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd"
+ urn:mace:shibboleth:2.0:attribute:encoder http://shibboleth.net/schema/idp/shibboleth-attribute-encoder.xsd"
/>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2String.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2String.xml
index 1300dd2..97ab520 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2String.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2String.xml
@@ -4,10 +4,12 @@
xmlns="urn:mace:shibboleth:2.0:resolver"
name="Saml2String_ATTRIBUTE_NAME"
nameFormat="Saml2String_ATTRIBUTE_NAME_FORMAT"
- friendlyName="Saml2String_ATTRIBUTE_FRIENDLY_NAME"
+ friendlyName="Saml2String_ATTRIBUTE_FRIENDLY_NAME"
+ encodeType="%{the.encodeType.property:false}"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
<ActivationConditionScript>
- <Script>false</Script>
- </ActivationConditionScript>
+ <Script>%{the.activation.property}</Script>
+ </ActivationConditionScript>
+
</AttributeEncoder>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2StringConditional.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2StringConditional.xml
index 741d16b..63c1736 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2StringConditional.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2StringConditional.xml
@@ -3,6 +3,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mace:shibboleth:2.0:resolver"
name="Saml2StringConditional"
- activationConditionRef="predicate"
+ activationConditionRef="shibboleth.Predicate"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd" />
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2StringDefault.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2StringDefault.xml
index ef45b88..1f04ab4 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2StringDefault.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2StringDefault.xml
@@ -3,5 +3,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mace:shibboleth:2.0:resolver"
name="Saml2StringName"
+ activationConditionRef="shibboleth.Predicate"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd" />
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2XmlObject.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2XmlObject.xml
index 0ef9d0e..97d74f0 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2XmlObject.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2XmlObject.xml
@@ -4,5 +4,12 @@
xmlns="urn:mace:shibboleth:2.0:resolver"
name="Saml2XmlObject_ATTRIBUTE_NAME"
nameFormat="Saml2XmlObject_ATTRIBUTE_NAME_FORMAT"
- friendlyName="Saml2XmlObject_ATTRIBUTE_FRIENDLY_NAME"
- xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"/>
\ No newline at end of file
+ friendlyName="Saml2XmlObject_ATTRIBUTE_FRIENDLY_NAME"
+ encodeType="%{the.encodeType.property:true}"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <ActivationConditionScript>
+ <Script>%{the.activation.property}</Script>
+ </ActivationConditionScript>
+
+</AttributeEncoder>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2XmlObjectDefault.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2XmlObjectDefault.xml
index f77cbf9..2339c03 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2XmlObjectDefault.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/enc/resolver/saml2XmlObjectDefault.xml
@@ -3,5 +3,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mace:shibboleth:2.0:resolver"
name="XmlObjectName"
+ activationConditionRef="shibboleth.Predicate"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd"/>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest-attributes.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest-attributes.xml
index 76b690b..6dacf39 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest-attributes.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest-attributes.xml
@@ -2,47 +2,45 @@
<AttributeResolver xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
- <!-- ========================================== -->
- <!-- Attribute Definitions -->
- <!-- ========================================== -->
-
- <DataConnector id="staticAttributes" xsi:type="Static">
- <Attribute id="assurance">
- <Value>tin</Value>
- <Value>pewter</Value>
- </Attribute>
- <Attribute id="oAssurance">
- <Value>bakelite</Value>
- <Value>dross</Value>
- </Attribute>
- <Attribute id="eduPersonEntitlement">
- <Value>urn:example.org:entitlement:entitlement1</Value>
- <Value>urn:mace:dir:entitlement:common-lib-terms</Value>
- </Attribute>
+ <!--
+ Unusable connector to ensure it's being lazily eval'd.
+ -->
+ <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
+ ldapURL="ldaps://localhost:6666"
+ baseDN="dc=shibboleth,dc=net"
+ connectTimeout="PT2S"
+ responseTimeout="PT2S"
+ principal="cn=Directory Manager"
+ principalCredential="password">
+ <FilterTemplate>
+ <![CDATA[
+ (uid=$resolutionContext.principal)
+ ]]>
+ </FilterTemplate>
</DataConnector>
<AttributeDefinition xsi:type="Simple" id="eduPersonAssurance">
- <InputDataConnector allAttributes="true" ref="staticAttributes" />
+ <InputDataConnector allAttributes="true" ref="myLDAP" />
<AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAssurance" />
<AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" friendlyName="feduPersonAssurance" />
<AttributeEncoder xsi:type="SAML2String" nameFormat="http://example.org/Format" name="http://example.org/name/for/Attribute" friendlyName="fotherSAMLName" />
</AttributeDefinition>
<AttributeDefinition xsi:type="Simple" id="otherPersonAssurance" >
- <InputDataConnector allAttributes="true" ref="staticAttributes" />
+ <InputDataConnector allAttributes="true" ref="myLDAP" />
<AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAssurance" />
<AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" friendlyName="feduPersonAssurance" />
</AttributeDefinition>
<AttributeDefinition xsi:type="Simple" id="otherFormatPersonAssurance" >
- <InputDataConnector allAttributes="true" ref="staticAttributes" />
+ <InputDataConnector allAttributes="true" ref="myLDAP" />
<AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAssurance" />
<AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" nameFormat="http://example.org/Format" friendlyName="fOeduPersonAssurance" />
</AttributeDefinition>
<AttributeDefinition xsi:type="Scoped" id="eduPersonScopedAffiliation" scope="example.org"
>
- <InputDataConnector allAttributes="true" ref="staticAttributes" />
+ <InputDataConnector allAttributes="true" ref="myLDAP" />
<AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" />
<AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" friendlyName="feduPersonScopedAffiliation"
scopeDelimiter='#'/>
@@ -50,7 +48,7 @@
<AttributeDefinition xsi:type="SAML2NameID" id="eduPersonTID"
nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" >
- <InputDataConnector allAttributes="true" ref="staticAttributes" />
+ <InputDataConnector allAttributes="true" ref="myLDAP" />
<AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" />
<AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="feduPersonTargetedID" />
</AttributeDefinition>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest.xml
index bf29c12..b86d5a7 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/mapperTest.xml
@@ -8,6 +8,9 @@
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-init-method="initialize"
default-destroy-method="destroy">
+
+ <import resource="customBean.xml" />
+
<bean id="shibboleth.VelocityEngine" class="net.shibboleth.ext.spring.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<props>
@@ -21,16 +24,17 @@
</props>
</property>
</bean>
- <bean id="shibboleth.AttributeResolverService" class="net.shibboleth.ext.spring.service.ReloadableSpringService"
- depends-on="shibboleth.VelocityEngine" p:failFast="false"
+
+ <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="TestID" />
+ <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 +42,14 @@
</util:list>
</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>
+
</beans>
\ No newline at end of file
diff --git a/idp-authn-api/.project b/idp-authn-api/.project
index eac45e1..8b15bc1 100644
--- a/idp-authn-api/.project
+++ b/idp-authn-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-authn-impl/.project b/idp-authn-impl/.project
index 93f0107..14170b7 100644
--- a/idp-authn-impl/.project
+++ b/idp-authn-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-bom/.project b/idp-bom/.project
index f286c93..937f4e2 100644
--- a/idp-bom/.project
+++ b/idp-bom/.project
@@ -6,11 +6,6 @@
</projects>
<buildSpec>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-cas-api/.project b/idp-cas-api/.project
index 23cfd9c..7db0de0 100644
--- a/idp-cas-api/.project
+++ b/idp-cas-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-cas-impl/.project b/idp-cas-impl/.project
index 22f763b..2adfe34 100644
--- a/idp-cas-impl/.project
+++ b/idp-cas-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-conf/.project b/idp-conf/.project
index 1f94f11..4c8f229 100644
--- a/idp-conf/.project
+++ b/idp-conf/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-conf/src/main/resources/attributes/saml1/eduPersonPrincipalName.txt b/idp-conf/src/main/resources/attributes/saml1/eduPersonPrincipalName.txt
new file mode 100644
index 0000000..008831d
--- /dev/null
+++ b/idp-conf/src/main/resources/attributes/saml1/eduPersonPrincipalName.txt
@@ -0,0 +1,4 @@
+id = eduPersonPrincipalName
+transcoder_bean = SAML1ScopedStringTranscoder
+name = urn:mace:dir:attribute-def:eduPersonPrincipalName
+encodeType = false
diff --git a/idp-conf/src/main/resources/attributes/saml1/eduPersonScopedAffiliation.txt b/idp-conf/src/main/resources/attributes/saml1/eduPersonScopedAffiliation.txt
new file mode 100644
index 0000000..e6c505b
--- /dev/null
+++ b/idp-conf/src/main/resources/attributes/saml1/eduPersonScopedAffiliation.txt
@@ -0,0 +1,4 @@
+id = eduPersonScopedAffiliation
+transcoder_bean = SAML1ScopedStringTranscoder
+name = urn:mace:dir:attribute-def:eduPersonScopedAffiliation
+encodeType = false
diff --git a/idp-conf/src/main/resources/attributes/saml1/mail.txt b/idp-conf/src/main/resources/attributes/saml1/mail.txt
new file mode 100644
index 0000000..22f4da9
--- /dev/null
+++ b/idp-conf/src/main/resources/attributes/saml1/mail.txt
@@ -0,0 +1,4 @@
+id = mail
+transcoder_bean = SAML1StringTranscoder
+name = urn:mace:dir:attribute-def:mail
+encodeType = false
diff --git a/idp-conf/src/main/resources/attributes/saml1/uid.txt b/idp-conf/src/main/resources/attributes/saml1/uid.txt
new file mode 100644
index 0000000..209d6a0
--- /dev/null
+++ b/idp-conf/src/main/resources/attributes/saml1/uid.txt
@@ -0,0 +1,4 @@
+id = uid
+transcoder_bean = SAML1StringTranscoder
+name = urn:mace:dir:attribute-def:uid
+encodeType = false
diff --git a/idp-conf/src/main/resources/attributes/saml2/eduPersonPrincipalName.txt b/idp-conf/src/main/resources/attributes/saml2/eduPersonPrincipalName.txt
new file mode 100644
index 0000000..970f0da
--- /dev/null
+++ b/idp-conf/src/main/resources/attributes/saml2/eduPersonPrincipalName.txt
@@ -0,0 +1,4 @@
+id = eduPersonPrincipalName
+transcoder_bean = SAML2ScopedStringTranscoder
+name = urn:oid:1.3.6.1.4.1.5923.1.1.1.6
+encodeType = false
diff --git a/idp-conf/src/main/resources/attributes/saml2/eduPersonScopedAffiliation.txt b/idp-conf/src/main/resources/attributes/saml2/eduPersonScopedAffiliation.txt
new file mode 100644
index 0000000..aedfcb5
--- /dev/null
+++ b/idp-conf/src/main/resources/attributes/saml2/eduPersonScopedAffiliation.txt
@@ -0,0 +1,4 @@
+id = eduPersonScopedAffiliation
+transcoder_bean = SAML2ScopedStringTranscoder
+name = urn:oid:1.3.6.1.4.1.5923.1.1.1.9
+encodeType = false
diff --git a/idp-conf/src/main/resources/attributes/saml2/mail.txt b/idp-conf/src/main/resources/attributes/saml2/mail.txt
new file mode 100644
index 0000000..8e28190
--- /dev/null
+++ b/idp-conf/src/main/resources/attributes/saml2/mail.txt
@@ -0,0 +1,4 @@
+id = mail
+transcoder_bean = SAML2StringTranscoder
+name = urn:oid:0.9.2342.19200300.100.1.3
+encodeType = false
diff --git a/idp-conf/src/main/resources/attributes/saml2/uid.txt b/idp-conf/src/main/resources/attributes/saml2/uid.txt
new file mode 100644
index 0000000..0f259a9
--- /dev/null
+++ b/idp-conf/src/main/resources/attributes/saml2/uid.txt
@@ -0,0 +1,4 @@
+id = uid
+transcoder_bean = SAML2StringTranscoder
+name = urn:oid:0.9.2342.19200300.100.1.1
+encodeType = false
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml b/idp-conf/src/main/resources/conf/attribute-registry.xml
similarity index 67%
copy from idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml
copy to idp-conf/src/main/resources/conf/attribute-registry.xml
index ef730da..da86845 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml
+++ b/idp-conf/src/main/resources/conf/attribute-registry.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
@@ -10,17 +11,8 @@
default-init-method="initialize"
default-destroy-method="destroy">
- <util:map id="shibboleth.CustomScriptObject">
- <entry key="foo" value="bar"/>
- </util:map>
- <util:map id="other.CustomScriptObject">
- <entry key="bar" value="foo"/>
- </util:map>
-
- <bean id="shibboleth.PropertySourcesPlaceholderConfigurer"
- class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"
- p:placeholderPrefix="%{" p:placeholderSuffix="}" />
+ <!-- Default location for mappings. -->
+ <bean parent="shibboleth.TranscodingRuleLoader" c:_0="%{idp.home}/attributes" />
+
</beans>
-
-
\ No newline at end of file
diff --git a/idp-conf/src/main/resources/conf/attribute-resolver.xml b/idp-conf/src/main/resources/conf/attribute-resolver.xml
index 471bf0b..d6b479e 100644
--- a/idp-conf/src/main/resources/conf/attribute-resolver.xml
+++ b/idp-conf/src/main/resources/conf/attribute-resolver.xml
@@ -32,8 +32,6 @@
-->
<AttributeDefinition id="eduPersonPrincipalName" xsi:type="Scoped" scope="%{idp.scope}">
<InputAttributeDefinition ref="uid" />
- <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonPrincipalName" encodeType="false" />
- <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" friendlyName="eduPersonPrincipalName" encodeType="false" />
</AttributeDefinition>
<!--
@@ -41,10 +39,7 @@
representing a local username, but you should generally *never*
expose uid to federated services, as it is rarely globally unique.
-->
- <AttributeDefinition id="uid" xsi:type="PrincipalName">
- <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:uid" encodeType="false" />
- <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.1" friendlyName="uid" encodeType="false" />
- </AttributeDefinition>
+ <AttributeDefinition id="uid" xsi:type="PrincipalName" />
<!--
In the rest of the world, the email address is the standard identifier,
@@ -53,8 +48,6 @@
-->
<AttributeDefinition id="mail" xsi:type="Template">
<InputAttributeDefinition ref="uid" />
- <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:mail" encodeType="false" />
- <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.3" friendlyName="mail" encodeType="false" />
<Template>
<![CDATA[
${uid}@example.org
@@ -68,8 +61,6 @@
-->
<AttributeDefinition id="eduPersonScopedAffiliation" xsi:type="Scoped" scope="%{idp.scope}">
<InputDataConnector ref="staticAttributes" attributeNames="affiliation" />
- <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" encodeType="false" />
- <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" friendlyName="eduPersonScopedAffiliation" encodeType="false" />
</AttributeDefinition>
diff --git a/idp-conf/src/main/resources/conf/services.properties b/idp-conf/src/main/resources/conf/services.properties
index 9e9b102..257dade 100644
--- a/idp-conf/src/main/resources/conf/services.properties
+++ b/idp-conf/src/main/resources/conf/services.properties
@@ -21,6 +21,11 @@ idp.service.relyingparty.checkInterval = PT15M
#idp.service.metadata.failFast = false
#idp.service.metadata.checkInterval = PT0S
+# Set to shibboleth.LegacyAttributeRegistryResources to support only AttributeEncoders
+#idp.service.attribute.registry.resources = shibboleth.AttributeRegistryResources
+#idp.service.attribute.registry.failFast = false
+idp.service.attribute.registry.checkInterval = PT15M
+
#idp.service.attribute.resolver.resources = shibboleth.AttributeResolverResources
#idp.service.attribute.resolver.failFast = false
idp.service.attribute.resolver.checkInterval = PT15M
diff --git a/idp-conf/src/main/resources/conf/services.xml b/idp-conf/src/main/resources/conf/services.xml
index e04ac8f..558ae50 100644
--- a/idp-conf/src/main/resources/conf/services.xml
+++ b/idp-conf/src/main/resources/conf/services.xml
@@ -69,6 +69,18 @@
<value>%{idp.home}/conf/attribute-resolver.xml</value>
</util:list>
+ <!-- This set of resources relies on (at least) the new registry mappings. -->
+ <util:list id ="shibboleth.AttributeRegistryResources">
+ <value>%{idp.home}/conf/attribute-registry.xml</value>
+ <value>%{idp.home}/system/conf/attribute-registry-system.xml</value>
+ </util:list>
+
+ <!-- This set of resources uses only AttributeEncoders for compatibility. -->
+ <util:list id ="shibboleth.LegacyAttributeRegistryResources">
+ <value>%{idp.home}/conf/attribute-resolver.xml</value>
+ <value>%{idp.home}/system/conf/attribute-registry-system.xml</value>
+ </util:list>
+
<util:list id ="shibboleth.AttributeFilterResources">
<value>%{idp.home}/conf/attribute-filter.xml</value>
</util:list>
diff --git a/idp-conf/src/main/resources/system/conf/attribute-registry-system.xml b/idp-conf/src/main/resources/system/conf/attribute-registry-system.xml
new file mode 100644
index 0000000..cf21b80
--- /dev/null
+++ b/idp-conf/src/main/resources/system/conf/attribute-registry-system.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.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="SAML2StringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2StringAttributeTranscoder" />
+ <bean id="SAML2ScopedStringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ScopedStringAttributeTranscoder" />
+ <bean id="SAML2ByteTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ByteAttributeTranscoder" />
+ <bean id="SAML2XMLObjectTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2XMLObjectAttributeTranscoder" />
+
+ <bean id="SAML1StringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1StringAttributeTranscoder" />
+ <bean id="SAML1ScopedStringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ScopedStringAttributeTranscoder" />
+ <bean id="SAML1ByteTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ByteAttributeTranscoder" />
+ <bean id="SAML1XMLObjectTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1XMLObjectAttributeTranscoder" />
+
+ <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.TranscodingRule"
+ class="net.shibboleth.idp.attribute.transcoding.TranscodingRule" abstract="true" />
+
+ <bean id="shibboleth.TranscodingRuleLoader"
+ class="net.shibboleth.idp.attribute.transcoding.impl.TranscodingRuleLoader" abstract="true" />
+
+</beans>
diff --git a/idp-conf/src/main/resources/system/conf/services-system.xml b/idp-conf/src/main/resources/system/conf/services-system.xml
index 8718a7f..8062fdc 100644
--- a/idp-conf/src/main/resources/system/conf/services-system.xml
+++ b/idp-conf/src/main/resources/system/conf/services-system.xml
@@ -54,6 +54,26 @@
</constructor-arg>
</bean>
+ <bean id="shibboleth.AttributeRegistryService" class="net.shibboleth.ext.spring.service.ReloadableSpringService"
+ p:serviceConfigurations-ref="#{
+ getObject('%{idp.service.attribute.registry.resources:shibboleth.AttributeRegistryResources}'.trim()) != null
+ ? '%{idp.service.attribute.registry.resources:shibboleth.AttributeRegistryResources}'.trim()
+ : 'shibboleth.DefaultAttributeRegistryResources' }"
+ p:failFast="%{idp.service.attribute.registry.failFast:%{idp.service.failFast:false}}"
+ p:reloadCheckDelay="%{idp.service.attribute.registry.checkInterval:PT0S}"
+ p:beanPostProcessors-ref="shibboleth.IdentifiableBeanPostProcessor"
+ p:beanFactoryPostProcessors-ref="shibboleth.PropertySourcesPlaceholderConfigurer">
+ <constructor-arg name="claz" value="net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry" />
+ <constructor-arg name="strategy">
+ <bean class="net.shibboleth.idp.attribute.transcoding.spring.impl.AttributeRegistryServiceStrategy"
+ p:namingRegistry="#{'%{idp.service.attribute.registry.namingRegistry:DefaultNamingRegistry}'.trim()}" />
+ </constructor-arg>
+ </bean>
+ <util:list id ="shibboleth.DefaultAttributeRegistryResources">
+ <value>%{idp.home}/conf/attribute-registry.xml</value>
+ <value>%{idp.home}/system/conf/attribute-registry-system.xml</value>
+ </util:list>
+
<bean id="shibboleth.NameIdentifierGenerationService" class="net.shibboleth.ext.spring.service.ReloadableSpringService"
c:claz="net.shibboleth.idp.saml.nameid.NameIdentifierGenerationService"
p:serviceConfigurations-ref="#{'%{idp.service.nameidGeneration.resources:shibboleth.NameIdentifierGenerationResources}'.trim()}"
@@ -76,7 +96,7 @@
</bean>
<bean id="shibboleth.MetadataResolverService" class="net.shibboleth.ext.spring.service.ReloadableSpringService"
- depends-on="shibboleth.AttributeResolverService"
+ depends-on="shibboleth.AttributeRegistryService"
p:serviceConfigurations-ref="#{'%{idp.service.metadata.resources:shibboleth.MetadataResolverResources}'.trim()}"
p:failFast="%{idp.service.metadata.failFast:%{idp.service.failFast:false}}"
p:reloadCheckDelay="%{idp.service.metadata.checkInterval:PT0S}"
@@ -89,7 +109,7 @@
<list>
<ref bean="shibboleth.IdentifiableBeanPostProcessor" />
<bean class="net.shibboleth.idp.profile.spring.relyingparty.metadata.impl.NodeProcessingAttachingBeanPostProcessor"
- c:service-ref="shibboleth.AttributeResolverService" />
+ c:service-ref="shibboleth.AttributeRegistryService" />
</list>
</property>
</bean>
@@ -159,14 +179,6 @@
class="net.shibboleth.utilities.java.support.security.DelegatingAccessControlService"
c:acService-ref="shibboleth.ReloadableAccessControlService" />
- <bean id="shibboleth.SAML1AttributeDesignatorsMapperService"
- class="net.shibboleth.idp.saml.attribute.mapping.impl.SAML1AttributeDesignatorsMapperService"
- c:resolverService-ref="shibboleth.AttributeResolverService" />
-
- <bean id="shibboleth.SAML2AttributesMapperService"
- class="net.shibboleth.idp.saml.attribute.mapping.impl.SAML2AttributesMapperService"
- c:resolverService-ref="shibboleth.AttributeResolverService" />
-
<bean id="shibboleth.CASServiceRegistry"
class="net.shibboleth.idp.cas.service.impl.ReloadingServiceRegistry"
c:delegate-ref="shibboleth.ReloadableCASServiceRegistry" />
diff --git a/idp-conf/src/main/resources/system/flows/admin/status-beans.xml b/idp-conf/src/main/resources/system/flows/admin/status-beans.xml
index 3428e17..75da1bf 100644
--- a/idp-conf/src/main/resources/system/flows/admin/status-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/admin/status-beans.xml
@@ -32,6 +32,7 @@
<ref bean="shibboleth.MetadataResolverService" />
<ref bean="shibboleth.RelyingPartyResolverService" />
<ref bean="shibboleth.NameIdentifierGenerationService" />
+ <ref bean="shibboleth.AttributeRegistryService" />
<ref bean="shibboleth.AttributeResolverService" />
<ref bean="shibboleth.AttributeFilterService" />
<ref bean="shibboleth.ReloadableCASServiceRegistry" />
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml
index 1bedd54..71bcfd2 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml
@@ -87,7 +87,7 @@
<bean id="MapRequestedAttributesInAttributeConsumingService" scope="prototype"
class="net.shibboleth.idp.saml.saml2.profile.impl.MapRequestedAttributesInAttributeConsumingService"
- p:resolverService-ref="shibboleth.AttributeResolverService" />
+ p:transcoderRegistry-ref="shibboleth.AttributeRegistryService" />
<bean id="InitializeRelyingPartyContexFromSAMLPeer"
class="net.shibboleth.idp.saml.profile.impl.InitializeRelyingPartyContextFromSAMLPeer" scope="prototype" />
@@ -239,14 +239,6 @@
p:maskFailures="%{idp.service.attribute.filter.maskFailures:true}"
p:metadataResolver-ref="shibboleth.MetadataResolver" />
- <bean id="FilterByQueriedAttributeDesignators"
- class="net.shibboleth.idp.saml.saml1.profile.impl.FilterByQueriedAttributeDesignators" scope="prototype"
- c:mapper-ref="shibboleth.SAML1AttributeDesignatorsMapperService" />
-
- <bean id="FilterByQueriedAttributes"
- class="net.shibboleth.idp.saml.saml2.profile.impl.FilterByQueriedAttributes" scope="prototype"
- c:mapper-ref="shibboleth.SAML2AttributesMapperService" />
-
<bean id="PopulatePostAuthnInterceptContext"
class="net.shibboleth.idp.profile.interceptor.impl.PopulateProfileInterceptorContext" scope="prototype"
p:availableFlows-ref="shibboleth.AvailableInterceptFlows">
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml1/attribute-query-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml1/attribute-query-beans.xml
index 4cf0537..974d005 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml1/attribute-query-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml1/attribute-query-beans.xml
@@ -41,6 +41,10 @@
class="net.shibboleth.utilities.java.support.logic.FunctionSupport" factory-method="constant"
c:_0-ref="shibboleth.OutgoingSOAPBindings" />
+ <bean id="FilterByQueriedAttributeDesignators"
+ class="net.shibboleth.idp.saml.saml1.profile.impl.FilterByQueriedAttributeDesignators" scope="prototype"
+ p:transcoderRegistry-ref="shibboleth.AttributeRegistryService" />
+
<bean id="CopyNameIdentifierFromRequest"
class="org.opensaml.saml.saml1.profile.impl.CopyNameIdentifierFromRequest" scope="prototype" />
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml1/common-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml1/common-beans.xml
index 9e74e4e..b184b1c 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml1/common-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml1/common-beans.xml
@@ -48,7 +48,8 @@
</bean>
<bean id="AddAttributeStatementToAssertion"
- class="net.shibboleth.idp.saml.saml1.profile.impl.AddAttributeStatementToAssertion" scope="prototype">
+ class="net.shibboleth.idp.saml.saml1.profile.impl.AddAttributeStatementToAssertion" scope="prototype"
+ p:transcoderRegistry-ref="shibboleth.AttributeRegistryService">
<property name="activationCondition">
<bean class="net.shibboleth.idp.saml.profile.config.logic.IncludeAttributeStatementPredicate" />
</property>
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml2/attribute-query-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml2/attribute-query-beans.xml
index 9fe154e..27bd70d 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml2/attribute-query-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml2/attribute-query-beans.xml
@@ -41,6 +41,10 @@
class="net.shibboleth.utilities.java.support.logic.FunctionSupport" factory-method="constant"
c:_0-ref="shibboleth.OutgoingSOAPBindings" />
+ <bean id="FilterByQueriedAttributes"
+ class="net.shibboleth.idp.saml.saml2.profile.impl.FilterByQueriedAttributes" scope="prototype"
+ p:transcoderRegistry-ref="shibboleth.AttributeRegistryService" />
+
<bean id="CopyNameIDFromRequest"
class="org.opensaml.saml.saml2.profile.impl.CopyNameIDFromRequest" scope="prototype" />
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml2/common-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml2/common-beans.xml
index 2272ff0..4ba739c 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml2/common-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml2/common-beans.xml
@@ -62,7 +62,8 @@
</bean>
<bean id="AddAttributeStatementToAssertion"
- class="net.shibboleth.idp.saml.saml2.profile.impl.AddAttributeStatementToAssertion" scope="prototype">
+ class="net.shibboleth.idp.saml.saml2.profile.impl.AddAttributeStatementToAssertion" scope="prototype"
+ p:transcoderRegistry-ref="shibboleth.AttributeRegistryService">
<property name="activationCondition">
<bean class="net.shibboleth.idp.saml.profile.config.logic.IncludeAttributeStatementPredicate" />
</property>
diff --git a/idp-conf/src/test/java/net/shibboleth/idp/test/flows/mapper/MappingTest.java b/idp-conf/src/test/java/net/shibboleth/idp/test/flows/mapper/MappingTest.java
index d26af09..4c0c74e 100644
--- a/idp-conf/src/test/java/net/shibboleth/idp/test/flows/mapper/MappingTest.java
+++ b/idp-conf/src/test/java/net/shibboleth/idp/test/flows/mapper/MappingTest.java
@@ -28,7 +28,7 @@ import org.testng.annotations.Test;
*/
@ContextConfiguration({"classpath:/mapping/configs/override.xml", })
public class MappingTest extends AbstractFlowTest {
- @Test public void testResolveAndFilter() {
+ @Test(enabled=true) public void testResolveAndFilter() {
final FlowExecutionResult result = flowExecutor.launchExecution("resolveAndFilter", null, externalContext);
diff --git a/idp-conf/src/test/java/net/shibboleth/idp/test/flows/mapper/TestAfterFilter.java b/idp-conf/src/test/java/net/shibboleth/idp/test/flows/mapper/TestAfterFilter.java
index b6db71f..4bd9ed5 100644
--- a/idp-conf/src/test/java/net/shibboleth/idp/test/flows/mapper/TestAfterFilter.java
+++ b/idp-conf/src/test/java/net/shibboleth/idp/test/flows/mapper/TestAfterFilter.java
@@ -39,13 +39,13 @@ public class TestAfterFilter extends AbstractProfileAction {
AttributeContext ac = rpc.getSubcontext(AttributeContext.class);
- Assert.assertNotNull(ac.getIdPAttributes().get("IdPRA1"));
- Assert.assertFalse(ac.getIdPAttributes().get("IdPRA1").getValues().isEmpty());
+ Assert.assertNull(ac.getIdPAttributes().get("IdPNotOK"));
Assert.assertNull(ac.getIdPAttributes().get("IdPEA1"));
Assert.assertNotNull(ac.getIdPAttributes().get("IdPOK"));
Assert.assertFalse(ac.getIdPAttributes().get("IdPOK").getValues().isEmpty());
- Assert.assertNull(ac.getIdPAttributes().get("IdPNotOK"));
-
+
+ Assert.assertNotNull(ac.getIdPAttributes().get("IdPRA1"));
+ Assert.assertFalse(ac.getIdPAttributes().get("IdPRA1").getValues().isEmpty());
}
}
diff --git a/idp-conf/src/test/java/net/shibboleth/idp/test/flows/saml1/SAML1AttributeQueryFlowTest.java b/idp-conf/src/test/java/net/shibboleth/idp/test/flows/saml1/SAML1AttributeQueryFlowTest.java
index a1b83a4..92d8bec 100644
--- a/idp-conf/src/test/java/net/shibboleth/idp/test/flows/saml1/SAML1AttributeQueryFlowTest.java
+++ b/idp-conf/src/test/java/net/shibboleth/idp/test/flows/saml1/SAML1AttributeQueryFlowTest.java
@@ -161,7 +161,7 @@ public class SAML1AttributeQueryFlowTest extends AbstractSAML1FlowTest {
designator.setAttributeNamespace(SAMLConstants.SAML1_ATTR_NAMESPACE_URI);
designator.setAttributeName("urn:mace:dir:attribute-def:mail");
attributeQuery.getAttributeQuery().getAttributeDesignators().add(designator);
-
+
designator = designatorBuilder.buildObject();
designator.setAttributeNamespace(SAMLConstants.SAML1_ATTR_NAMESPACE_URI);
designator.setAttributeName("urn:mace:dir:attribute-def:foo");
diff --git a/idp-conf/src/test/java/net/shibboleth/idp/test/flows/saml2/SAML2AttributeQueryFlowTest.java b/idp-conf/src/test/java/net/shibboleth/idp/test/flows/saml2/SAML2AttributeQueryFlowTest.java
index e16930d..b994561 100644
--- a/idp-conf/src/test/java/net/shibboleth/idp/test/flows/saml2/SAML2AttributeQueryFlowTest.java
+++ b/idp-conf/src/test/java/net/shibboleth/idp/test/flows/saml2/SAML2AttributeQueryFlowTest.java
@@ -170,7 +170,7 @@ public class SAML2AttributeQueryFlowTest extends AbstractSAML2FlowTest {
XSAny value = valueBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
value.setTextContent("jdoe at example.org");
designator.getAttributeValues().add(value);
-
+
designator = designatorBuilder.buildObject();
designator.setNameFormat(Attribute.URI_REFERENCE);
designator.setName("urn:mace:dir:attribute-def:foo");
diff --git a/idp-conf/src/test/resources/mapping/configs/attribute-filter.xml b/idp-conf/src/test/resources/mapping/configs/attribute-filter.xml
index c690913..0d9edc7 100644
--- a/idp-conf/src/test/resources/mapping/configs/attribute-filter.xml
+++ b/idp-conf/src/test/resources/mapping/configs/attribute-filter.xml
@@ -28,7 +28,7 @@
</AttributeFilterPolicy>
- <!-- Release is EA map -->
+ <!-- Release if EA map -->
<AttributeFilterPolicy id="EAOKFILTER">
<PolicyRequirementRule id="prrEA1" xsi:type="EntityAttributeExactMatch"
attributeName="http://macedir.org/entity-category"
diff --git a/idp-conf/src/test/resources/mapping/configs/attribute-resolver.xml b/idp-conf/src/test/resources/mapping/configs/attribute-resolver.xml
index ec1cdf5..6acdcfd 100644
--- a/idp-conf/src/test/resources/mapping/configs/attribute-resolver.xml
+++ b/idp-conf/src/test/resources/mapping/configs/attribute-resolver.xml
@@ -17,7 +17,6 @@ Part 1 of a two part attribute resolver.
<AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1" friendlyName="eduPersonAffiliation" />
</AttributeDefinition>
-
<DataConnector id="staticAttributes" xsi:type="Static">
<Attribute id="ra_1">
<Value>RA1</Value>
@@ -46,5 +45,4 @@ Part 1 of a two part attribute resolver.
name="http://example.org/result"
nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" friendlyName="OKOUT" />
</AttributeDefinition>
-
</AttributeResolver>
diff --git a/idp-conf/src/test/resources/mapping/configs/override.xml b/idp-conf/src/test/resources/mapping/configs/override.xml
index aa47df8..2c0a499 100644
--- a/idp-conf/src/test/resources/mapping/configs/override.xml
+++ b/idp-conf/src/test/resources/mapping/configs/override.xml
@@ -18,4 +18,9 @@
<value>classpath:/mapping/configs/attribute-filter2.xml</value>
</util:list>
+ <util:list id ="shibboleth.AttributeRegistryResources">
+ <value>classpath:/system/conf/attribute-registry-system.xml</value>
+ <value>classpath:/mapping/configs/attribute-resolver.xml</value>
+ <value>classpath:/mapping/configs/attribute-resolver2.xml</value>
+ </util:list>
</beans>
\ No newline at end of file
diff --git a/idp-consent-api/.project b/idp-consent-api/.project
index 62a8236..b2139c1 100644
--- a/idp-consent-api/.project
+++ b/idp-consent-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-consent-impl/.project b/idp-consent-impl/.project
index 2201166..31861b6 100644
--- a/idp-consent-impl/.project
+++ b/idp-consent-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
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-core/.project b/idp-core/.project
index d914eaf..df54311 100644
--- a/idp-core/.project
+++ b/idp-core/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-installer/.project b/idp-installer/.project
index e3f990e..bba0631 100644
--- a/idp-installer/.project
+++ b/idp-installer/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-profile-api/.project b/idp-profile-api/.project
index 818e804..6a29367 100644
--- a/idp-profile-api/.project
+++ b/idp-profile-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-profile-impl/.project b/idp-profile-impl/.project
index 8f46927..4a93d08 100644
--- a/idp-profile-impl/.project
+++ b/idp-profile-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-profile-spring/.project b/idp-profile-spring/.project
index 585e593..a586093 100644
--- a/idp-profile-spring/.project
+++ b/idp-profile-spring/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
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/.project b/idp-saml-api/.project
index dc7374d..4fdf337 100644
--- a/idp-saml-api/.project
+++ b/idp-saml-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-saml-api/pom.xml b/idp-saml-api/pom.xml
index 525ed29..3b02eba 100644
--- a/idp-saml-api/pom.xml
+++ b/idp-saml-api/pom.xml
@@ -76,7 +76,6 @@
<groupId>${opensaml.groupId}</groupId>
<artifactId>opensaml-xmlsec-api</artifactId>
</dependency>
-
<dependency>
<groupId>${spring.groupId}</groupId>
<artifactId>spring-beans</artifactId>
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML1AttributeEncoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML1AttributeEncoder.java
deleted file mode 100644
index aa80232..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML1AttributeEncoder.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding;
-
-import java.util.List;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeDesignatorMapper;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.logic.ConstraintViolationException;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.saml.common.SAMLObjectBuilder;
-import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml1.core.Attribute;
-
-import com.google.common.base.Objects;
-
-/**
- * Base class for encoders that produce a SAML 1 {@link Attribute}.
- *
- * @param <EncodedType> the type of data that can be encoded by the encoder
- */
-public abstract class AbstractSAML1AttributeEncoder<EncodedType extends IdPAttributeValue>
- extends AbstractSAMLAttributeEncoder<Attribute, EncodedType>
- implements SAML1AttributeEncoder<EncodedType>, AttributeDesignatorMapperProcessor<IdPAttribute> {
-
- /** Builder used to construct {@link Attribute} objects. */
- @Nonnull private final SAMLObjectBuilder<Attribute> attributeBuilder;
-
- /** The namespace in which the attribute name is interpreted. */
- @NonnullAfterInit private String namespace;
-
- /** Constructor. */
- public AbstractSAML1AttributeEncoder() {
- attributeBuilder =
- (SAMLObjectBuilder<Attribute>) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(
- Attribute.TYPE_NAME);
- if (attributeBuilder == null) {
- throw new ConstraintViolationException("SAML 1 Attribute builder is unavailable");
- }
- namespace = net.shibboleth.idp.saml.xml.SAMLConstants.SAML1_ATTR_NAMESPACE_URI;
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull @NotEmpty public final String getProtocol() {
- return SAMLConstants.SAML11P_NS;
- }
-
- /** {@inheritDoc} */
- @Override @NonnullAfterInit public String getNamespace() {
- return namespace;
- }
-
- /**
- * Set the namespace in which the attribute name is interpreted.
- *
- * @param attributeNamespace namespace in which the attribute name is interpreted
- */
- public void setNamespace(@Nonnull @NotEmpty final String attributeNamespace) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- namespace = Constraint.isNotNull(StringSupport.trimOrNull(attributeNamespace),
- "Attribute namespace cannot be null or empty");
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
-
- if (namespace == null) {
- throw new ComponentInitializationException("Attribute namespace cannot be null or empty");
- }
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull protected Attribute buildAttribute(@Nonnull final IdPAttribute idpAttribute,
- @Nonnull @NonnullElements final List<XMLObject> attributeValues) throws AttributeEncodingException {
-
- final Attribute samlAttribute = attributeBuilder.buildObject();
- samlAttribute.setAttributeName(getName());
- samlAttribute.setAttributeNamespace(getNamespace());
- samlAttribute.getAttributeValues().addAll(attributeValues);
-
- return samlAttribute;
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull public void populateAttributeMapper(
- @Nonnull final AbstractSAMLAttributeDesignatorMapper<IdPAttribute> mapper) {
- mapper.setAttributeNamespace(getNamespace());
- mapper.setId(getMapperId());
- mapper.setSAMLName(getName());
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(final Object obj) {
-
- if (!super.equals(obj)) {
- return false;
- }
-
- if (!(obj instanceof AbstractSAML1AttributeEncoder)) {
- return false;
- }
-
- final AbstractSAML1AttributeEncoder other = (AbstractSAML1AttributeEncoder) obj;
- return java.util.Objects.equals(getNamespace(), other.getNamespace());
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return Objects.hashCode(super.hashCode(), getNamespace());
- }
-
- /**
- * Generate an Id suitable for the mapper.
- *
- * @return a suitable Id for the mapper
- */
- @Nonnull @NotEmpty private String getMapperId() {
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
- return "MapperForAttribute" + getName();
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML2AttributeEncoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML2AttributeEncoder.java
deleted file mode 100644
index af37398..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML2AttributeEncoder.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding;
-
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.ConstraintViolationException;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.saml.common.SAMLObjectBuilder;
-import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml2.core.Attribute;
-
-import com.google.common.base.Objects;
-
-/**
- * Base class for encoders that produce a SAML 2 {@link Attribute}.
- *
- * @param <EncodedType> the type of data that can be encoded by the encoder
- */
-public abstract class AbstractSAML2AttributeEncoder<EncodedType extends IdPAttributeValue> extends
- AbstractSAMLAttributeEncoder<Attribute, EncodedType> implements SAML2AttributeEncoder<EncodedType> {
-
- /** Builder used to construct {@link Attribute} objects. */
- @Nonnull private final SAMLObjectBuilder<Attribute> attributeBuilder;
-
- /** A friendly, human readable, name for the attribute. */
- @Nullable private String friendlyName;
-
- /** The format of the attribute name. */
- @Nullable private String format;
-
- /** Constructor. */
- public AbstractSAML2AttributeEncoder() {
- attributeBuilder =
- (SAMLObjectBuilder<Attribute>) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(
- Attribute.TYPE_NAME);
- if (attributeBuilder == null) {
- throw new ConstraintViolationException("SAML 2 Attribute builder is unavailable");
- }
- setNameFormat(Attribute.URI_REFERENCE);
- }
-
- /** {@inheritDoc} */
- @Override @Nonnull public final String getProtocol() {
- return SAMLConstants.SAML20P_NS;
- }
-
- /**
- * Get the friendly, human readable, name for the attribute.
- *
- * @return friendly, human readable, name for the attribute
- */
- @Nullable public final String getFriendlyName() {
- return friendlyName;
- }
-
- /**
- * Set the friendly, human readable, name for the attribute.
- *
- * @param attributeFriendlyName friendly, human readable, name for the attribute
- */
- public void setFriendlyName(@Nullable final String attributeFriendlyName) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- friendlyName = StringSupport.trimOrNull(attributeFriendlyName);
- }
-
- /** {@inheritDoc} */
- @Override
- @Nullable public String getNameFormat() {
- return format;
- }
-
- /**
- * Get the name format, or the SAML constants for "unspecified", if not set.
- *
- * @return the effective name format regardless of nulls
- */
- @Nonnull @NotEmpty public String getEffectiveNameFormat() {
- return format != null ? format : Attribute.UNSPECIFIED;
- }
-
- /**
- * Set the format of the attribute name.
- *
- * @param nameFormat format in which the attribute name is interpreted
- */
- public void setNameFormat(@Nullable final String nameFormat) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- format = StringSupport.trimOrNull(nameFormat);
- }
-
- /** {@inheritDoc} */
- @Override @Nonnull protected Attribute buildAttribute(@Nonnull final IdPAttribute idpAttribute,
- @Nonnull @NonnullElements final List<XMLObject> attributeValues) throws AttributeEncodingException {
-
- final Attribute samlAttribute = attributeBuilder.buildObject();
- samlAttribute.setName(getName());
- samlAttribute.setFriendlyName(getFriendlyName());
- samlAttribute.setNameFormat(getNameFormat());
- samlAttribute.getAttributeValues().addAll(attributeValues);
-
- return samlAttribute;
- }
-
- /**
- * Generate an Id suitable for the mapper.
- *
- * @return a suitable Id for the mapper
- */
- @Nonnull protected String getMapperId() {
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
- if (null != getFriendlyName()) {
- return "MapperFor" + getFriendlyName();
- }
- return "MapperForAttribute" + getName();
- }
-
- /** {@inheritDoc} */
- @Override public boolean equals(final Object obj) {
-
- if (!super.equals(obj)) {
- return false;
- }
-
- if (!(obj instanceof AbstractSAML2AttributeEncoder)) {
- return false;
- }
-
- final AbstractSAML2AttributeEncoder other = (AbstractSAML2AttributeEncoder) obj;
- return java.util.Objects.equals(getEffectiveNameFormat(), other.getEffectiveNameFormat());
- }
-
- /** {@inheritDoc} */
- @Override public int hashCode() {
- return Objects.hashCode(super.hashCode(), getEffectiveNameFormat());
- }
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAMLAttributeEncoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAMLAttributeEncoder.java
deleted file mode 100644
index 1e7f36b..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAMLAttributeEncoder.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Predicate;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.AttributeEncoder;
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.component.UnmodifiableComponent;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.saml.common.SAMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Predicates;
-
-/**
- * Base class for encoders that produce SAML attributes.
- *
- * @param <AttributeType> type of attribute produced
- * @param <EncodedType> the type of data that can be encoded by the encoder
- */
-public abstract class AbstractSAMLAttributeEncoder<AttributeType extends SAMLObject,
- EncodedType extends IdPAttributeValue> extends AbstractInitializableComponent
- implements AttributeEncoder<AttributeType>, UnmodifiableComponent {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractSAMLAttributeEncoder.class);
-
- /** Condition for use of this encoder. */
- @Nonnull private Predicate<ProfileRequestContext> activationCondition;
-
- /** The name of the attribute. */
- @NonnullAfterInit private String name;
-
- /** Whether to encode with xsi:type or not. */
- private boolean encodeType;
-
- /** Constructor. */
- public AbstractSAMLAttributeEncoder() {
- activationCondition = Predicates.alwaysTrue();
- encodeType = true;
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull public Predicate<ProfileRequestContext> getActivationCondition() {
- return activationCondition;
- }
-
- /**
- * Set the activation condition for this encoder.
- *
- * @param condition condition to set
- */
- public void setActivationCondition(@Nonnull final Predicate<ProfileRequestContext> condition) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- activationCondition = Constraint.isNotNull(condition, "Activation condition cannot be null");
- }
-
- /**
- * Get the name of the attribute.
- *
- * @return name of the attribute
- */
- @NonnullAfterInit public final String getName() {
- return name;
- }
-
- /**
- * Set the name of the attribute.
- *
- * @param attributeName name of the attribute
- */
- public void setName(@Nonnull @NotEmpty final String attributeName) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- name = Constraint.isNotNull(StringSupport.trimOrNull(attributeName),
- "Attribute name cannot be null or empty");
- }
-
- /**
- * Get whether to encode type information.
- *
- * <p>Defaults to 'true'</p>
- *
- * @return true iff type information should be encoded
- */
- public boolean encodeType() {
- return encodeType;
- }
-
- /**
- * Set whether to encode type information.
- *
- * @param flag flag to set
- */
- public void setEncodeType(final boolean flag) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- encodeType = flag;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
-
- if (name == null) {
- throw new ComponentInitializationException("Attribute name cannot be null or empty");
- }
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull public AttributeType encode(@Nonnull final IdPAttribute attribute) throws AttributeEncodingException {
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
- Constraint.isNotNull(attribute, "Attribute to encode cannot be null");
- final String attributeId = attribute.getId();
- log.debug("Beginning to encode attribute {}", attributeId);
-
- if (attribute.getValues().isEmpty()) {
- throw new AttributeEncodingException("Unable to encode " + attributeId
- + " attribute. It does not contain any values");
- }
-
- final List<XMLObject> samlAttributeValues = new ArrayList<>();
-
- EncodedType attributeValue;
- XMLObject samlAttributeValue;
- for (final IdPAttributeValue o : attribute.getValues()) {
- if (o == null) {
- // filtered out upstream leave in test for sanity
- log.debug("Skipping null value of attribute {}", attributeId);
- continue;
- }
-
- if (!canEncodeValue(attribute, o)) {
- log.warn("Skipping value of attribute '{}'; Type {} cannot be encoded by this encoder ({}).",
- attributeId, o.getClass().getName(), this.getClass().getName());
- continue;
- }
-
- attributeValue = (EncodedType) o;
- samlAttributeValue = encodeValue(attribute, attributeValue);
- if (samlAttributeValue == null) {
- log.debug("Skipping empty value for attribute {}", attributeId);
- } else {
- samlAttributeValues.add(samlAttributeValue);
- }
- }
-
- if (samlAttributeValues.isEmpty()) {
- throw new AttributeEncodingException("Attribute " + attributeId + " did not contain any encodeable values");
- }
-
- log.debug("Completed encoding {} values for attribute {}", samlAttributeValues.size(), attributeId);
- return buildAttribute(attribute, samlAttributeValues);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(final Object obj) {
- if (obj == null) {
- return false;
- }
-
- if (obj == this) {
- return true;
- }
-
- if (!(obj instanceof AbstractSAMLAttributeEncoder)) {
- return false;
- }
-
- final AbstractSAMLAttributeEncoder other = (AbstractSAMLAttributeEncoder) obj;
- return java.util.Objects.equals(getName(), other.getName())
- && java.util.Objects.equals(getProtocol(), other.getProtocol());
- }
-
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return Objects.hashCode(getName(), getProtocol());
- }
-
- /**
- * Checks if the given value can be handled by the encoder. In many cases this is simply a check to see if the given
- * object is of the right type.
- *
- * @param idpAttribute the attribute being encoded, never null
- * @param value the value to check, never null
- *
- * @return true if the encoder can encoder this value, false if not
- */
- protected abstract boolean canEncodeValue(@Nonnull final IdPAttribute idpAttribute,
- @Nonnull final IdPAttributeValue value);
-
- /**
- * Encodes an attribute value in to a SAML attribute value element.
- *
- * @param idpAttribute the attribute being encoded, never null
- * @param value the value to encoder, never null
- *
- * @return the attribute value or null if the resulting attribute value would be empty
- *
- * @throws AttributeEncodingException thrown if there is a problem encoding the attribute value
- */
- @Nullable protected abstract XMLObject encodeValue(@Nonnull final IdPAttribute idpAttribute,
- @Nonnull final EncodedType value) throws AttributeEncodingException;
-
- /**
- * Builds a SAML attribute element from the given attribute values.
- *
- * @param idpAttribute the attribute being encoded, never null
- * @param attributeValues the encoded values for the attribute, never null or containing null elements
- *
- * @return the SAML attribute element
- *
- * @throws AttributeEncodingException thrown if there is a problem constructing the SAML attribute
- */
- @Nonnull protected abstract AttributeType buildAttribute(@Nonnull final IdPAttribute idpAttribute,
- @Nonnull @NonnullElements final List<XMLObject> attributeValues) throws AttributeEncodingException;
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AttributeDesignatorMapperProcessor.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AttributeDesignatorMapperProcessor.java
deleted file mode 100644
index cc420b9..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AttributeDesignatorMapperProcessor.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeDesignatorMapper;
-
-/**
- * An interface which is implemented by encoders which encode SAML 1 attributes and which can be reverse mapped.
- *
- * @param <I> The IdP Type
- */
-public interface AttributeDesignatorMapperProcessor<I extends IdPAttribute> {
-
- /**
- * This populates the attribute mapper to go from a SAML AttributeDesignator to an IdP Attribute (or
- * derivative) such that applying the output of the mapper to the encoder will produce the name attribute
- * (and vice versa).
- *
- * <p>The populated mapper <em>must not</em> have any associated (IdP) Attribute names and <em>must</em> implement
- * {@link Object#equals(Object)} and {@link Object#hashCode()}.</p>
- *
- * @param mapper the mapper.
- */
- @Nonnull void populateAttributeMapper(@Nonnull final AbstractSAMLAttributeDesignatorMapper<I> mapper);
-
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AttributeMapperProcessor.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AttributeMapperProcessor.java
deleted file mode 100644
index c676c88..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/AttributeMapperProcessor.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
-
-import org.opensaml.saml.saml2.core.Attribute;
-
-/**
- * An interface which is implemented by encoders which encode attributes and which can be reverse mapped.
- *
- * @param <S> The SAML Type
- * @param <I> The IdP Type
- */
-public interface AttributeMapperProcessor<S extends Attribute,I extends IdPAttribute> {
-
- /**
- * This populates the attribute mapper to go from a SAML Attribute (or derivative) to an IdP Attribute (or
- * derivative) such that applying the output of the mapper to the encoder will produce the name attribute
- * (and vice versa).
- *
- * <p>The populated mapper <em>must not</em> have any associated (IdP) Attribute names and <em>must</em> implement
- * {@link Object#equals(Object)} and {@link Object#hashCode()}.</p>
- *
- * @param mapper the mapper.
- */
- @Nonnull void populateAttributeMapper(@Nonnull final AbstractSAMLAttributeMapper<S, I> mapper);
-
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/SAML1AttributeEncoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/SAML1AttributeEncoder.java
deleted file mode 100644
index bcb202f..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/SAML1AttributeEncoder.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding;
-
-import net.shibboleth.idp.attribute.AttributeEncoder;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-
-import org.opensaml.saml.saml1.core.Attribute;
-
-
-/**
- * Interface for encoders that produce a SAML 1 {@link Attribute}.
- *
- * @param <EncodedType> the type of data that can be encoded by the encoder
- */
-public interface SAML1AttributeEncoder<EncodedType extends IdPAttributeValue> extends AttributeEncoder<Attribute> {
-
- /**
- * Get the encoded Name of the attribute.
- *
- * @return name of the attribute
- */
- @NonnullAfterInit String getName();
-
- /**
- * Get the encoded Namespace of the attribute.
- *
- * @return namespace of the attribute
- */
- @NonnullAfterInit String getNamespace();
-
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeDesignatorMapper.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeDesignatorMapper.java
deleted file mode 100644
index 0e0495f..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeDesignatorMapper.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.annotation.constraint.NullableElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
-import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.opensaml.saml.saml1.core.AttributeDesignator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-
-/**
- * Basis of all classes which map SAML1 {@link AttributeDesignator} into an IdP {@link IdPAttribute}.
- *
- * @param <OutType> the output (IdP Attribute) type
- */
-public abstract class AbstractSAMLAttributeDesignatorMapper<OutType extends IdPAttribute> extends
- AbstractIdentifiableInitializableComponent implements AttributeMapper<AttributeDesignator, OutType> {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractSAMLAttributeDesignatorMapper.class);
-
- /** The internal names to generate. */
- @Nonnull @NonnullElements private List<String> attributeIds = Collections.emptyList();
-
- /** The attribute namespace. */
- @Nullable private String attributeNamespace;
-
- /** the (SAML) attribute name. */
- @NonnullAfterInit private String theSAMLName;
-
- /** The String used to prefix log message. */
- @Nullable private String logPrefix;
-
- /**
- * Set the list of internal identifiers.
- *
- * @param theIds the list
- */
- public void setAttributeIds(@Nullable @NullableElements final List<String> theIds) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- if (null == theIds) {
- return;
- }
-
- attributeIds = ImmutableList.copyOf(StringSupport.normalizeStringCollection(theIds));
- }
-
- /**
- * Get the list of internal identifiers.
- *
- * @return the identifiers
- */
- @Nonnull @NonnullElements @Unmodifiable public List<String> getAttributeIds() {
- return attributeIds;
- }
-
- /**
- * Set the SAML attribute name.
- *
- * @param name the name
- */
- public void setSAMLName(@Nullable final String name) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- theSAMLName = StringSupport.trimOrNull(name);
- }
-
- /**
- * Get the SAML attribute name.
- *
- * @return the name
- */
- @NonnullAfterInit public String getSAMLName() {
- return theSAMLName;
- }
-
- /**
- * Set the (optional) attribute namespace.
- *
- * @param ns the namespace to set
- */
- public void setAttributeNamespace(@Nullable final String ns) {
- attributeNamespace = StringSupport.trimOrNull(ns);
- }
-
- /**
- * Get the (optional) attribute namespace.
- *
- * @return the namespace
- */
- @Nullable public String getAttributeNamespace() {
- return attributeNamespace;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
- if (null == theSAMLName) {
- throw new ComponentInitializationException(getLogPrefix() + " SAML name not present");
- }
- if (attributeIds.isEmpty()) {
- throw new ComponentInitializationException(getLogPrefix()
- + " At least one attribute Id should be provided");
- }
- logPrefix = null;
- }
-
- /**
- * Compare whether the name and namespace given "match" ours. Used in checking both against input attributes and as
- * part of equality checking.
- *
- * @param otherSAMLName the name to compare against
- * @param otherSAMLNamespace the bamespace to compare against
- * @return whether there is a match.
- */
- protected boolean matches(@Nonnull @NotEmpty final String otherSAMLName,
- @Nullable final String otherSAMLNamespace) {
- if (!otherSAMLName.equals(theSAMLName)) {
- log.debug("{} SAML attribute name {} does not match {}", getLogPrefix(), otherSAMLName, getId());
- return false;
- } else if (!java.util.Objects.equals(otherSAMLNamespace, getAttributeNamespace())) {
- log.debug("{} SAML attribute namespace {} does not match {}", getLogPrefix(), otherSAMLNamespace,
- getAttributeNamespace());
- return false;
- }
-
- return true;
- }
-
- /**
- * Determines if the input matches the provided parameterisation.
- *
- * @param designator the designator to consider
- * @return whether it matches.
- */
- protected boolean attributeMatches(@Nonnull final AttributeDesignator designator) {
- return matches(designator.getAttributeName(), designator.getAttributeNamespace());
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull @NonnullElements public Map<String,OutType> mapAttribute(@Nonnull final AttributeDesignator prototype) {
-
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
-
- if (!attributeMatches(prototype)) {
- return Collections.emptyMap();
- }
-
- final Map<String,OutType> output = new HashMap<>();
-
- log.debug("{} attribute id {} and aliases {} will be created", getLogPrefix(), getId(), getAttributeIds());
-
- OutType out = newAttribute(prototype, getId());
-
- for (final String id : attributeIds) {
- out = newAttribute(prototype, getId());
- output.put(id, out);
- }
- return output;
- }
-
- /**
- * return a string which is to be prepended to all log messages.
- *
- * @return "<type> Attribute Mapper '<mapper ID>' :"
- */
- @Nonnull @NotEmpty protected String getLogPrefix() {
- // local cache of cached entry to allow unsynchronised clearing.
- String prefix = logPrefix;
- if (null == prefix) {
- final StringBuilder builder = new StringBuilder();
-
- builder.append("Attribute Mapper '").append(getId()).append("':");
- prefix = builder.toString();
- if (null == logPrefix) {
- logPrefix = prefix;
- }
- }
- return prefix;
- }
-
- /**
- * {@inheritDoc}. The identity is not part of equality of hash
- */
- @Override
- public boolean equals(final Object obj) {
- if (obj == null) {
- return false;
- }
-
- if (obj == this) {
- return true;
- }
-
- if (obj instanceof AbstractSAMLAttributeDesignatorMapper) {
- final AbstractSAMLAttributeDesignatorMapper other = (AbstractSAMLAttributeDesignatorMapper) obj;
- return matches(other.getSAMLName(), other.getAttributeNamespace())
- && java.util.Objects.equals(getAttributeIds(), other.getAttributeIds());
- }
- return false;
- }
-
- /**
- * {@inheritDoc}. The identity is not part of equality of hash
- */
- @Override
- public int hashCode() {
- return Objects.hashCode(attributeNamespace, theSAMLName, attributeIds);
- }
-
- /**
- * Function to summon up the output type based on an ID and an object of the input type. Typically the input type
- * will be inspected for extra parameterisation.
- *
- * @param input the input value to inspect.
- * @param id the identifier of the new attribute.
- * @return an output, suitable set up with per object information.
- */
- @Nonnull protected abstract OutType newAttribute(@Nonnull final AttributeDesignator input,
- @Nonnull @NotEmpty final String id);
-
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeDesignatorsMapper.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeDesignatorsMapper.java
deleted file mode 100644
index cccd896..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeDesignatorsMapper.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.saml.saml1.core.AttributeDesignator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Supplier;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-
-import net.shibboleth.idp.attribute.AttributeEncoder;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
-import net.shibboleth.idp.saml.attribute.encoding.AttributeDesignatorMapperProcessor;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.collection.Pair;
-import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-
-/**
- * The class contains the mechanics to go from a list of {@link AttributeDesignator}s to a {@link Multimap} of
- * {@link String},{@link IdPAttribute} (or derived, or null). The representation as a {@link Multimap} is useful for
- * filtering situations and is exploited by the AttributeInMetadata filter.
- *
- * @param <OutType> some sort of representation of an IdP attribute
- */
-public abstract class AbstractSAMLAttributeDesignatorsMapper<OutType extends IdPAttribute>
- extends AbstractIdentifiableInitializableComponent implements AttributesMapper<AttributeDesignator,OutType> {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractSAMLAttributeDesignatorsMapper.class);
-
- /** The mappers we can apply. */
- @Nonnull @NonnullElements private Collection<AttributeMapper<AttributeDesignator,OutType>> mappers;
-
- /** The String used to prefix log message. */
- @Nullable private String logPrefix;
-
- /** Default Constructor. */
- public AbstractSAMLAttributeDesignatorsMapper() {
- mappers = Collections.emptyList();
- }
-
- /**
- * Constructor to create the mapping from an existing resolver.
- *
- * <p>This code inverts the {@link AttributeEncoder} (internal attribute -> SAML Attributes) into
- * {@link AttributeMapper} (SAML [AttributeDesignators] -> internal [Requested] Attributes). <br/>
- * to generate the {@link AbstractSAMLAttributeDesignatorMapper} (with no
- * {@link AbstractSAMLAttributeDesignatorMapper#getAttributeIds()}. These are accumulated into a {@link Multimap},
- * where the key is the {@link AbstractSAMLAttributeDesignatorMapper} and the values are the (IdP) attribute names.
- * The collection of {@link AttributeMapper}s can then be extracted from the map, and the appropriate internal names
- * added (these being the value of the {@link Multimap})</p>
- *
- * @param resolver the resolver
- * @param id the ID
- * @param mapperFactory factory to generate new mappers of the correct type.
- */
- public AbstractSAMLAttributeDesignatorsMapper(@Nonnull final AttributeResolver resolver,
- @Nonnull @NotEmpty final String id,
- @Nonnull final Supplier<AbstractSAMLAttributeDesignatorMapper<OutType>> mapperFactory) {
-
- setId(id);
- mappers = Collections.emptyList();
-
- final Multimap<AbstractSAMLAttributeDesignatorMapper<OutType>,String> theMappers = HashMultimap.create();
-
- for (final Pair<String, AttributeEncoder<?>> pair : resolver.getAllEncoders()) {
- if (pair.getSecond() instanceof AttributeDesignatorMapperProcessor) {
- // There is an appropriate reverse mapper.
- final AttributeDesignatorMapperProcessor factory =
- (AttributeDesignatorMapperProcessor) pair.getSecond();
- final AbstractSAMLAttributeDesignatorMapper<OutType> mapper = mapperFactory.get();
- factory.populateAttributeMapper(mapper);
-
- theMappers.put(mapper, pair.getFirst());
- }
- }
-
- mappers = new ArrayList<>(theMappers.values().size());
-
- for (final Entry<AbstractSAMLAttributeDesignatorMapper<OutType>,Collection<String>> entry
- : theMappers.asMap().entrySet()) {
-
- final AbstractSAMLAttributeDesignatorMapper<OutType> mapper = entry.getKey();
- mapper.setAttributeIds(new ArrayList<>(entry.getValue()));
- mappers.add(mapper);
- }
- }
-
- /**
- * Get the mappers.
- *
- * @return Returns the mappers.
- */
- @Nonnull @NonnullElements public Collection<AttributeMapper<AttributeDesignator,OutType>> getMappers() {
- return mappers;
- }
-
- /**
- * Set the attribute mappers into the lookup map.
- *
- * @param theMappers The mappers to set.
- */
- public void setMappers(@Nonnull final Collection<AttributeMapper<AttributeDesignator,OutType>> theMappers) {
- mappers = Constraint.isNotNull(theMappers, "Mappers list cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull @NonnullElements public Multimap<String,OutType> mapAttributes(
- @Nonnull @NonnullElements final List<AttributeDesignator> prototypes) {
-
- final Multimap<String,OutType> result = ArrayListMultimap.create();
-
- for (final AttributeDesignator prototype : prototypes) {
- for (final AttributeMapper<AttributeDesignator,OutType> mapper : mappers) {
-
- final Map<String,OutType> mappedAttributes = mapper.mapAttribute(prototype);
-
- log.debug("{} SAML attribute '{}' mapped to {} attributes by mapper '{}'", getLogPrefix(),
- prototype.getAttributeName(), mappedAttributes.size(), mapper.getId());
-
- for (final Entry<String,OutType> entry : mappedAttributes.entrySet()) {
- result.put(entry.getKey(), entry.getValue());
- }
- }
- }
- return result;
- }
-
- /** {@inheritDoc} */
- @Override protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
-
- logPrefix = null;
- for (final AttributeMapper mapper : mappers) {
- ComponentSupport.initialize(mapper);
- }
- }
-
- /**
- * Return a string which is to be prepended to all log messages.
- *
- * @return "Attribute Mappers '<ID>' :"
- */
- @Nonnull @NotEmpty private String getLogPrefix() {
- String s = logPrefix;
- if (null == s) {
- s = new StringBuilder("Attribute Mappers : '").append(getId()).append("':").toString();
- logPrefix = s;
- }
- return s;
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeMapper.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeMapper.java
deleted file mode 100644
index 217de97..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeMapper.java
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.annotation.constraint.NullableElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
-import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.saml2.core.Attribute;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-
-/**
- * Basis of all classes which map SAML2 {@link Attribute} into an IdP {@link IdPAttribute}.
- *
- * @param <InType> the input (SAML2 attribute) type
- * @param <OutType> the output (IdP Attribute) type
- */
-public abstract class AbstractSAMLAttributeMapper<InType extends Attribute, OutType extends IdPAttribute> extends
- AbstractIdentifiableInitializableComponent implements AttributeMapper<InType, OutType> {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractSAMLAttributeMapper.class);
-
- /** The internal names to generate. */
- @Nonnull @NonnullElements private List<String> attributeIds = Collections.emptyList();
-
- /** The attribute format. */
- @Nullable private String attributeFormat;
-
- /** the (SAML) attribute name. */
- @NonnullAfterInit private String theSAMLName;
-
- /** The String used to prefix log message. */
- @Nullable private String logPrefix;
-
- /** The value mapper. */
- @NonnullAfterInit private AbstractSAMLAttributeValueMapper valueMapper;
-
- /**
- * Set the list of internal identifiers.
- *
- * @param theIds the list
- */
- public void setAttributeIds(@Nullable @NullableElements final List<String> theIds) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- if (null == theIds) {
- return;
- }
-
- attributeIds = ImmutableList.copyOf(StringSupport.normalizeStringCollection(theIds));
- }
-
- /**
- * Get the list of internal identifiers.
- *
- * @return the identifiers
- */
- @Nonnull @NonnullElements @Unmodifiable public List<String> getAttributeIds() {
- return attributeIds;
- }
-
- /**
- * Set the SAML attribute name.
- *
- * @param name the name
- */
- public void setSAMLName(@Nullable final String name) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- theSAMLName = StringSupport.trimOrNull(name);
- }
-
- /**
- * Get the SAML attribute name.
- *
- * @return the name
- */
- @NonnullAfterInit public String getSAMLName() {
- return theSAMLName;
- }
-
- /**
- * Get the class which converts types.
- *
- * @param mapper The valueMapper to set.
- */
- public void setValueMapper(@Nullable final AbstractSAMLAttributeValueMapper mapper) {
- valueMapper = mapper;
- }
-
- /**
- * Get the class which converts types.
- *
- * @return Returns the valueMapper.
- */
- @NonnullAfterInit public AbstractSAMLAttributeValueMapper getValueMapper() {
- return valueMapper;
- }
-
- /**
- * Set the (optional) attribute format.
- *
- * @param format the format
- */
- public void setAttributeFormat(@Nullable final String format) {
- attributeFormat = StringSupport.trimOrNull(format);
- }
-
- /**
- * Get the (optional) attribute format.
- *
- * @return the format
- */
- @Nullable public String getAttributeFormat() {
- return attributeFormat;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
- if (null == theSAMLName) {
- throw new ComponentInitializationException(getLogPrefix() + " SAML name not present");
- }
- if (null == valueMapper) {
- throw new ComponentInitializationException(getLogPrefix() + " No value mapper present");
- }
- if (attributeIds.isEmpty()) {
- throw new ComponentInitializationException(getLogPrefix()
- + " At least one attribute Id should be provided");
- }
- logPrefix = null;
- valueMapper.setLogPrefix(getLogPrefix());
- }
-
- /**
- * Compare whether the name and format given "match" ours. Used in checking both against input attributes and as
- * part of equality checking. For the sake of comparison null is considered to be the same as
- * {@link Attribute#UNSPECIFIED}
- *
- * @param otherSAMLName the name to compare against
- * @param otherSAMLFormat the format to compare against
- * @return whether there is a match.
- */
- protected boolean matches(@Nonnull @NotEmpty final String otherSAMLName, @Nullable final String otherSAMLFormat) {
- if (!otherSAMLName.equals(theSAMLName)) {
- log.debug("{} SAML attribute name {} does not match {}", getLogPrefix(), otherSAMLName, getId());
- return false;
- }
-
- String format = otherSAMLFormat;
- if (format != null && Attribute.UNSPECIFIED.equals(format)) {
- format = null;
- }
-
- if (getAttributeFormat() != null && format != null && !getAttributeFormat().equals(format)
- && !Attribute.UNSPECIFIED.equals(getAttributeFormat())) {
- log.debug("{} SAML name format {} does not match {}", getLogPrefix(), format, getAttributeFormat());
- return false;
- }
- return true;
-
- }
-
- /**
- * Determines if the attribute matches the provided parameterisation.
- *
- * @param attribute the attribute to consider
- * @return whether it matches.
- */
- protected boolean attributeMatches(@Nonnull final InType attribute) {
- return matches(attribute.getName(), attribute.getNameFormat());
- }
-
- /** {@inheritDoc} */
- @Override @Nonnull @NonnullElements public Map<String,OutType> mapAttribute(@Nonnull final InType prototype) {
-
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
-
- if (!attributeMatches(prototype)) {
- return Collections.emptyMap();
- }
-
- final List<XMLObject> inputValues = prototype.getAttributeValues();
- final List<IdPAttributeValue<?>> outputValues = getValueMapper().decodeValues(inputValues);
-
- if (!inputValues.isEmpty() && outputValues.isEmpty()) {
- log.warn("{} Attribute '{}' value conversion yielded no suitable values", getLogPrefix(),
- prototype.getName());
- return Collections.emptyMap();
- }
-
- final Map<String,OutType> output = new HashMap<>(inputValues.size());
-
- log.debug("{} attribute id {} and aliases {} will be created", getLogPrefix(), getId(), getAttributeIds());
-
- OutType out = newAttribute(prototype, getId());
- out.setValues(outputValues);
-
- for (final String id : attributeIds) {
- out = newAttribute(prototype, getId());
- out.setValues(outputValues);
- output.put(id, out);
- }
- return output;
- }
-
- /**
- * return a string which is to be prepended to all log messages.
- *
- * @return "<type> Attribute Mapper '<mapper ID>' :"
- */
- @Nonnull @NotEmpty protected String getLogPrefix() {
- // local cache of cached entry to allow unsynchronised clearing.
- String prefix = logPrefix;
- if (null == prefix) {
- final StringBuilder builder = new StringBuilder();
- if (null != getValueMapper()) {
- builder.append(getValueMapper().getAttributeTypeName()).append(" ");
- }
-
- builder.append("Attribute Mapper '").append(getId()).append("':");
- prefix = builder.toString();
- if (null == logPrefix) {
- logPrefix = prefix;
- }
- }
- return prefix;
- }
-
- /**
- * {@inheritDoc}. The identity is not part of equality of hash
- */
- @Override
- public boolean equals(final Object obj) {
- if (obj == null) {
- return false;
- }
-
- if (obj == this) {
- return true;
- }
-
- if (obj instanceof AbstractSAMLAttributeMapper) {
- final AbstractSAMLAttributeMapper other = (AbstractSAMLAttributeMapper) obj;
- return matches(other.getSAMLName(), other.getAttributeFormat())
- && java.util.Objects.equals(getAttributeIds(), other.getAttributeIds());
- }
- return false;
- }
-
- /**
- * {@inheritDoc}. The identity is not part of equality of hash
- */
- @Override
- public int hashCode() {
- String myFormat = getAttributeFormat();
- if (null == myFormat) {
- myFormat = Attribute.UNSPECIFIED;
- }
- return Objects.hashCode(myFormat, theSAMLName, attributeIds);
- }
-
- /**
- * Function to summon up the output type based on an ID and an object of the input type. Typically the input type
- * will be inspected for extra parameterisation.
- *
- * @param input the input value to inspect.
- * @param id the identifier of the new attribute.
- * @return an output, suitable set up with per object information.
- */
- @Nonnull protected abstract OutType newAttribute(@Nonnull final InType input, @Nonnull @NotEmpty final String id);
-
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeValueMapper.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeValueMapper.java
deleted file mode 100644
index 1f1e78f..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributeValueMapper.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping;
-
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-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.AbstractInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.xml.DOMTypeSupport;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.schema.XSAny;
-import org.opensaml.core.xml.schema.XSBase64Binary;
-import org.opensaml.core.xml.schema.XSBoolean;
-import org.opensaml.core.xml.schema.XSDateTime;
-import org.opensaml.core.xml.schema.XSInteger;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.core.xml.schema.XSURI;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-
-/**
- * The base of the classes that map SAML2 attribute values into IdP attribute values.
- */
-public abstract class AbstractSAMLAttributeValueMapper extends AbstractInitializableComponent {
-
- /** logger. */
- private final Logger log = LoggerFactory.getLogger(AbstractSAMLAttributeValueMapper.class);
-
- /** The String used to prefix log message. */
- private String logPrefix;
-
- /**
- * Convert from a list of the SAML Objects (usually a SAML2 AttributeValue) Value into the IDP Attributes.
- *
- * @param inputs the list of SAML Attributes
- * @return a list of IdP Attributes
- */
- @Nonnull @Unmodifiable public List<IdPAttributeValue<?>>
- decodeValues(@Nonnull @NonnullElements final List<XMLObject> inputs) {
- final List<IdPAttributeValue<?>> outputs = new ArrayList<>(inputs.size());
-
- for (final XMLObject input : inputs) {
- final IdPAttributeValue output = decodeValue(input);
- if (null != output) {
- outputs.add(output);
- }
- }
- return Collections.unmodifiableList(outputs);
-
- }
-
- /**
- * Function to return the string contents if this is the correct type.
- *
- * @param object The object to inspect.
- * @return Its contents suitably decoded. Returns null if we could not decode.
- */
- // Checkstyle: CyclomaticComplexity OFF
- @Nullable protected String getStringValue(@Nonnull final XMLObject object) {
- String retVal = null;
-
- if (object instanceof XSString) {
-
- retVal = ((XSString) object).getValue();
-
- } else if (object instanceof XSURI) {
-
- retVal = ((XSURI) object).getValue();
-
- } else if (object instanceof XSBoolean) {
-
- retVal = ((XSBoolean) object).getValue().getValue() ? "1" : "0";
-
- } else if (object instanceof XSInteger) {
-
- retVal = ((XSInteger) object).getValue().toString();
-
- } else if (object instanceof XSDateTime) {
-
- final Instant dt = ((XSDateTime) object).getValue();
- if (dt != null) {
- retVal = DOMTypeSupport.instantToString(dt);
- } else {
- retVal = null;
- }
-
- } else if (object instanceof XSBase64Binary) {
-
- retVal = ((XSBase64Binary) object).getValue();
-
- } else if (object instanceof XSAny) {
-
- final XSAny wc = (XSAny) object;
- if (wc.getUnknownAttributes().isEmpty() && wc.getUnknownXMLObjects().isEmpty()) {
- retVal = wc.getTextContent();
- } else {
- retVal = null;
- }
- }
-
- if (null == retVal) {
- log.info("{} value of type {} could not be converted", getLogPrefix(), object.getClass().toString());
- }
- return retVal;
- }
-
- // Checkstyle: CyclomaticComplexity ON
-
- /**
- * Return a string which is to be prepended to all log messages. This is set by the enclosing AttributeMapper.
- *
- * @return Returns the logPrefix.
- */
- @NonnullAfterInit public String getLogPrefix() {
- return logPrefix;
- }
-
- /**
- * Set the log prefix to use.
- *
- * @param prefix The logPrefix to set.
- */
- public void setLogPrefix(@Nonnull final String prefix) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- logPrefix = Constraint.isNotNull(prefix, "prefix can not be null or empty");
- }
-
- /** {@inheritDoc} */
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
- if (null == logPrefix) {
- throw new ComponentInitializationException("No log prefix set");
- }
- }
-
- /** {@inheritDoc} */
- public boolean equals(final Object obj) {
- if (obj == null) {
- return false;
- }
-
- if (obj == this) {
- return true;
- }
-
- if (obj instanceof AbstractSAMLAttributeValueMapper) {
- final AbstractSAMLAttributeValueMapper other = (AbstractSAMLAttributeValueMapper) obj;
-
- return getClass().equals(other.getClass());
- }
- return false;
- }
-
- /** {@inheritDoc} */
- public int hashCode() {
- return Objects.hashCode(getClass());
- }
-
- /**
- * Function to decode a single {@link XMLObject} into an {@link IdPAttributeValue}.
- *
- * @param object the object to decode
- * @return the returned final {@link IdPAttributeValue} or null if decoding failed
- */
- @Nullable protected abstract IdPAttributeValue decodeValue(@Nonnull final XMLObject object);
-
- /**
- * Return the output type (for logging).
- *
- * @return the output type.
- */
- @Nonnull protected abstract String getAttributeTypeName();
-
-}
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributesMapper.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributesMapper.java
deleted file mode 100644
index 61e88bb..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AbstractSAMLAttributesMapper.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.saml.saml2.core.Attribute;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Supplier;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-
-import net.shibboleth.idp.attribute.AttributeEncoder;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
-import net.shibboleth.idp.saml.attribute.encoding.AttributeMapperProcessor;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.collection.Pair;
-import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-
-/**
- * The class contains the mechanics to go from a list of {@link Attribute}s (or derived) to a {@link Multimap} of
- * {@link String},{@link IdPAttribute} (or derived, or null). The representation as a {@link Multimap} is useful for
- * filtering situations and is exploited by AttributeInMetadata filter.
- *
- * @param <InType> the type which is to be inspected and mapped
- * @param <OutType> some sort of representation of an IdP attribute
- */
-
-public abstract class AbstractSAMLAttributesMapper<InType extends Attribute, OutType extends IdPAttribute> extends
- AbstractIdentifiableInitializableComponent implements AttributesMapper<InType, OutType> {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractSAMLAttributesMapper.class);
-
- /** The mappers we can apply. */
- @Nonnull @NonnullElements private Collection<AttributeMapper<InType,OutType>> mappers = Collections.EMPTY_LIST;
-
- /** The String used to prefix log message. */
- @Nullable private String logPrefix;
-
- /** Default Constructor. */
- public AbstractSAMLAttributesMapper() {
-
- }
-
- /**
- * Constructor to create the mapping from an existing resolver. <br/>
- * This code inverts the {@link AttributeEncoder} (internal attribute -> SAML Attributes) into
- * {@link AttributeMapper} (SAML [RequestedAttributes] -> internal [Requested] Attributes). <br/>
- * to generate the {@link AbstractSAMLAttributeMapper} (with no
- * {@link AbstractSAMLAttributeMapper#getAttributeIds()}. These are accumulated into a {@link Multimap}, where the
- * key is the {@link AbstractSAMLAttributeMapper} and the values are the (IdP) attribute names. The collection of
- * {@link AttributeMapper}s can then be extracted from the map, and the appropriate internal names added (these
- * being the value of the {@link Multimap})
- *
- * @param resolver The resolver
- * @param id The it
- * @param mapperFactory A factory to generate new mappers of the correct type.
- */
- public AbstractSAMLAttributesMapper(@Nonnull final AttributeResolver resolver, @Nonnull @NotEmpty final String id,
- @Nonnull final Supplier<AbstractSAMLAttributeMapper<InType,OutType>> mapperFactory) {
-
- setId(id);
-
- final Multimap<AbstractSAMLAttributeMapper<InType,OutType>,String> theMappers;
-
- theMappers = HashMultimap.create();
-
- for (final Pair<String, AttributeEncoder<?>> pair : resolver.getAllEncoders()) {
- if (pair.getSecond() instanceof AttributeMapperProcessor) {
- // There is an appropriate reverse mapper
- final AttributeMapperProcessor factory = (AttributeMapperProcessor) pair.getSecond();
- final AbstractSAMLAttributeMapper<InType,OutType> mapper = mapperFactory.get();
- factory.populateAttributeMapper(mapper);
- theMappers.put(mapper, pair.getFirst());
- }
- }
-
- mappers = new ArrayList<>(theMappers.values().size());
-
- for (final Entry<AbstractSAMLAttributeMapper<InType,OutType>,Collection<String>> entry : theMappers.asMap()
- .entrySet()) {
-
- final AbstractSAMLAttributeMapper<InType, OutType> mapper = entry.getKey();
- mapper.setAttributeIds(new ArrayList<>(entry.getValue()));
- mappers.add(mapper);
- }
- }
-
- /**
- * Get the mappers.
- *
- * @return Returns the mappers.
- */
- @Nonnull @NonnullElements public Collection<AttributeMapper<InType,OutType>> getMappers() {
- return mappers;
- }
-
- /**
- * Set the attribute mappers into the lookup map.
- *
- * @param theMappers The mappers to set.
- */
- public void setMappers(@Nonnull final Collection<AttributeMapper<InType,OutType>> theMappers) {
- mappers = Constraint.isNotNull(theMappers, "mappers list must be non null");
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull @NonnullElements public Multimap<String,OutType> mapAttributes(
- @Nonnull @NonnullElements final List<InType> prototypes) {
-
- final Multimap<String,OutType> result = ArrayListMultimap.create();
-
- for (final InType prototype : prototypes) {
- for (final AttributeMapper<InType,OutType> mapper : mappers) {
-
- final Map<String,OutType> mappedAttributes;
- try {
- mappedAttributes = mapper.mapAttribute(prototype);
- } catch (final Exception e) {
- log.error("{} Attempt to map SAML attribute '{}' with mapper '{}' failed: ", getLogPrefix(),
- prototype.getName(),mapper.getId(), e);
- throw e;
- }
-
- log.debug("{} SAML attribute '{}' mapped to {} attributes by mapper '{}'", getLogPrefix(),
- prototype.getName(), mappedAttributes.size(), mapper.getId());
-
- for (final Entry<String,OutType> entry : mappedAttributes.entrySet()) {
- result.put(entry.getKey(), entry.getValue());
- }
- }
- }
- return result;
- }
-
- /** {@inheritDoc} */
- @Override protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
- logPrefix = null;
- for (final AttributeMapper mapper : mappers) {
- ComponentSupport.initialize(mapper);
- }
- }
-
- /**
- * Return a string which is to be prepended to all log messages.
- *
- * @return "Attribute Mappers '<ID>' :"
- */
- @Nonnull @NotEmpty private String getLogPrefix() {
- String s = logPrefix;
- if (null == s) {
- s = new StringBuilder("Attribute Mappers : '").append(getId()).append("':").toString();
- logPrefix = s;
- }
- return s;
- }
-}
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AttributeMapper.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AttributeMapper.java
deleted file mode 100644
index 45ee2a3..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AttributeMapper.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping;
-
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.component.IdentifiedComponent;
-
-/**
- * This attribute defines the mechanism to go from something into an (IdP) {@link IdPAttribute}. <br/>
- * Implementations of this interface will be paired with implementations of {@link AttributesMapper}.
- *
- * @param <InType> the type which is to be inspected and mapped
- * @param <OutType> some sort of representation of an IdP attribute
- */
-public interface AttributeMapper<InType,OutType extends IdPAttribute> extends IdentifiedComponent{
-
- /**
- * Map the SAML attribute to the required output type.
- *
- * <p>If the input contains values to be decoded, failure to decode any values results in a failure
- * to map the input at all.</p>
- *
- * @param input the SAML attribute
- * @return the appropriate map of names to output type
- *
- */
- @Nonnull @NonnullElements Map<String,OutType> mapAttribute(@Nonnull final InType input);
-
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AttributesMapper.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AttributesMapper.java
deleted file mode 100644
index e3cabc0..0000000
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/mapping/AttributesMapper.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping;
-
-import java.util.List;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-
-import com.google.common.collect.Multimap;
-
-/**
- * This attribute defines the mechanism to go from a list of objects into a collection (IdP) {@link IdPAttribute}, the
- * representation (a {@link Multimap}) being such as is useful to attribute filtering. <br/>
- * Implementations of this interface will be paired with implementations of {@link AttributeMapper}.
- *
- * @param <InType> the type which is to be inspected and mapped
- * @param <OutType> some sort of representation of an IdP attribute
- */
-public interface AttributesMapper<InType,OutType extends IdPAttribute> {
-
- /**
- * Map the input objects into IdP attributes.
- *
- * @param prototypes the SAML attributes
- *
- * @return a map from IdP AttributeId to RequestedAttributes
- */
- @Nonnull @NonnullElements Multimap<String,OutType> mapAttributes(
- @Nonnull @NonnullElements final List<InType> prototypes);
-
-}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java
new file mode 100644
index 0000000..0171c0f
--- /dev/null
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java
@@ -0,0 +1,187 @@
+/*
+ * 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.idp.saml.attribute.transcoding;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.xml.SAMLConstants;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml1.core.Attribute;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Strings;
+
+/**
+ * Base class for transcoders that operate on a SAML 1 {@link Attribute} or {@link AttributeDesignator}.
+ *
+ * @param <EncodedType> the type of data that can be handled by the transcoder
+ */
+public abstract class AbstractSAML1AttributeTranscoder<EncodedType extends IdPAttributeValue>
+ extends AbstractSAMLAttributeTranscoder<AttributeDesignator,EncodedType>
+ implements SAML1AttributeTranscoder<EncodedType> {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractSAML1AttributeTranscoder.class);
+
+ /** Builder used to construct {@link Attribute} objects. */
+ @Nonnull private final SAMLObjectBuilder<Attribute> attributeBuilder;
+
+ /** Builder used to construct {@link AttributeDesignator} objects. */
+ @Nonnull private final SAMLObjectBuilder<AttributeDesignator> designatorBuilder;
+
+ /** Constructor. */
+ public AbstractSAML1AttributeTranscoder() {
+ attributeBuilder = (SAMLObjectBuilder<Attribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
+ Attribute.TYPE_NAME);
+ designatorBuilder = (SAMLObjectBuilder<AttributeDesignator>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<AttributeDesignator>getBuilderOrThrow(
+ AttributeDesignator.TYPE_NAME);
+ }
+
+ /** {@inheritDoc} */
+ @Nonnull public Class<AttributeDesignator> getEncodedType() {
+ return AttributeDesignator.class;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable public String getEncodedName(@Nonnull final TranscodingRule rule) {
+
+ try {
+ // SAML 1 naming should be based on only what needs to be available from the properties alone.
+ return new NamingFunction().apply(buildAttribute(null, null, AttributeDesignator.class, rule,
+ Collections.emptyList()));
+ } catch (final AttributeEncodingException e) {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected AttributeDesignator buildAttribute(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nullable final IdPAttribute attribute, @Nonnull final Class<? extends AttributeDesignator> to,
+ @Nonnull final TranscodingRule rule, @Nonnull @NonnullElements final List<XMLObject> attributeValues)
+ throws AttributeEncodingException {
+
+ if (attribute != null && !attribute.getValues().isEmpty() && attributeValues.isEmpty()) {
+ throw new AttributeEncodingException("Failed to encode any values for attribute " + attribute.getId());
+ }
+
+ final String name = rule.get(PROP_NAME, String.class);
+ if (Strings.isNullOrEmpty(name)) {
+ throw new AttributeEncodingException("Required transcoder property 'name' not found");
+ }
+
+ final AttributeDesignator samlAttribute;
+
+ if (to.equals(Attribute.class)) {
+ if (attributeValues.isEmpty()) {
+ throw new AttributeEncodingException("Unable to encode a SAML 1 Attribute with no values");
+ }
+
+ samlAttribute = attributeBuilder.buildObject();
+ ((Attribute) samlAttribute).getAttributeValues().addAll(attributeValues);
+ } else if (to.equals(AttributeDesignator.class)) {
+ samlAttribute = designatorBuilder.buildObject();
+ if (!attributeValues.isEmpty()) {
+ log.warn("Lossy conversion to AttributeDesignator");
+ }
+ } else {
+ throw new AttributeEncodingException("Unsupported target object type: " + to.getName());
+ }
+
+ samlAttribute.setAttributeName(name);
+ samlAttribute.setAttributeNamespace(
+ rule.getOrDefault(PROP_NAMESPACE, String.class, SAMLConstants.SAML1_ATTR_NAMESPACE_URI));
+
+ return samlAttribute;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected IdPAttribute buildIdPAttribute(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
+ @Nonnull final TranscodingRule rule,
+ @Nonnull @NonnullElements final List<IdPAttributeValue<?>> attributeValues)
+ throws AttributeDecodingException {
+
+ final String id = rule.get(AttributeTranscoderRegistry.PROP_ID, String.class);
+ if (Strings.isNullOrEmpty(id)) {
+ throw new AttributeDecodingException("Required transcoder property 'id' not found");
+ }
+
+ final IdPAttribute idpAttribute;
+ if (attribute instanceof Attribute) {
+ if (!((Attribute) attribute).getAttributeValues().isEmpty() && attributeValues.isEmpty()) {
+ throw new AttributeDecodingException("Failed to decode any values for attribute "
+ + attribute.getAttributeName());
+ }
+ idpAttribute = new IdPAttribute(id);
+ } else {
+ idpAttribute = new IdPRequestedAttribute(id);
+ }
+
+ idpAttribute.setValues(attributeValues);
+
+ return idpAttribute;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected Iterable<XMLObject> getValues(@Nonnull final AttributeDesignator input) {
+ return input instanceof Attribute ? ((Attribute) input).getAttributeValues() : Collections.emptyList();
+ }
+
+ /** A function to produce a "canonical" name for a SAML 1 {@link AttributeDesignator} for transcoding rules. */
+ public static class NamingFunction implements Function<AttributeDesignator,String> {
+
+ /** {@inheritDoc} */
+ @Nullable public String apply(@Nullable final AttributeDesignator input) {
+
+ if (input == null || input.getAttributeName() == null || input.getAttributeNamespace() == null) {
+ return null;
+ }
+
+ final StringBuilder builder = new StringBuilder();
+ builder.append("SAML1:{").append(input.getAttributeNamespace()).append('}')
+ .append(input.getAttributeName());
+ return builder.toString();
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java
new file mode 100644
index 0000000..52e2b8d
--- /dev/null
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java
@@ -0,0 +1,188 @@
+/*
+ * 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.idp.saml.attribute.transcoding;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+
+import com.google.common.base.Strings;
+
+/**
+ * Base class for transcoders that operate on a SAML 2 {@link Attribute} or {@link RequestedAttribute}.
+ *
+ * @param <EncodedType> the type of data that can be handled by the transcoder
+ */
+public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAttributeValue> extends
+ AbstractSAMLAttributeTranscoder<Attribute,EncodedType> implements SAML2AttributeTranscoder<EncodedType> {
+
+ /** Builder used to construct {@link Attribute} objects. */
+ @Nonnull private final SAMLObjectBuilder<Attribute> attributeBuilder;
+
+ /** Builder used to construct {@link RequestedAttribute} objects. */
+ @Nonnull private final SAMLObjectBuilder<RequestedAttribute> reqAttributeBuilder;
+
+ /** Constructor. */
+ public AbstractSAML2AttributeTranscoder() {
+ attributeBuilder = (SAMLObjectBuilder<Attribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
+ Attribute.TYPE_NAME);
+ reqAttributeBuilder = (SAMLObjectBuilder<RequestedAttribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<RequestedAttribute>getBuilderOrThrow(
+ RequestedAttribute.TYPE_NAME);
+ }
+
+ /** {@inheritDoc} */
+ @Nonnull public Class<Attribute> getEncodedType() {
+ return Attribute.class;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable public String getEncodedName(@Nonnull final TranscodingRule rule) {
+
+ try {
+ // SAML 2 naming should be based on only what needs to be available from the properties alone.
+ return new NamingFunction().apply(buildAttribute(null, null, Attribute.class, rule,
+ Collections.emptyList()));
+ } catch (final AttributeEncodingException e) {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected Attribute buildAttribute(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nullable final IdPAttribute attribute, @Nonnull final Class<? extends Attribute> to,
+ @Nonnull final TranscodingRule rule, @Nonnull @NonnullElements final List<XMLObject> attributeValues)
+ throws AttributeEncodingException {
+
+ if (attribute != null && !attribute.getValues().isEmpty() && attributeValues.isEmpty()) {
+ throw new AttributeEncodingException("Failed to encode any values for attribute " + attribute.getId());
+ }
+
+ final String name = rule.get(PROP_NAME, String.class);
+ if (Strings.isNullOrEmpty(name)) {
+ throw new AttributeEncodingException("Required transcoder property 'name' not found");
+ }
+
+ final Attribute samlAttribute;
+
+ if (to.equals(Attribute.class)) {
+ samlAttribute = attributeBuilder.buildObject();
+ } else if (to.equals(RequestedAttribute.class)) {
+ samlAttribute = reqAttributeBuilder.buildObject();
+ if (attribute instanceof IdPRequestedAttribute) {
+ ((RequestedAttribute) samlAttribute).setIsRequired(((IdPRequestedAttribute) attribute).getIsRequired());
+ }
+ } else {
+ throw new AttributeEncodingException("Unsupported target object type: " + to.getName());
+ }
+
+ samlAttribute.setName(name);
+ samlAttribute.setNameFormat(rule.getOrDefault(PROP_NAME_FORMAT, String.class, Attribute.URI_REFERENCE));
+ samlAttribute.getAttributeValues().addAll(attributeValues);
+
+ final String friendlyName = rule.getOrDefault(PROP_FRIENDLY_NAME, String.class,
+ attribute != null ? attribute.getId() : "");
+ if (!friendlyName.isBlank()) {
+ samlAttribute.setFriendlyName(friendlyName);
+ }
+
+ return samlAttribute;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected IdPAttribute buildIdPAttribute(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
+ @Nonnull final TranscodingRule rule,
+ @Nonnull @NonnullElements final List<IdPAttributeValue<?>> attributeValues)
+ throws AttributeDecodingException {
+
+ if (!attribute.getAttributeValues().isEmpty() && attributeValues.isEmpty()) {
+ throw new AttributeDecodingException("Failed to decode any values for attribute " + attribute.getName());
+ }
+
+ final String id = rule.get(AttributeTranscoderRegistry.PROP_ID, String.class);
+ if (Strings.isNullOrEmpty(id)) {
+ throw new AttributeDecodingException("Required transcoder property 'id' not found");
+ }
+
+ final IdPAttribute idpAttribute;
+ if (attribute instanceof RequestedAttribute) {
+ idpAttribute = new IdPRequestedAttribute(id);
+ ((IdPRequestedAttribute) idpAttribute).setRequired(((RequestedAttribute) attribute).isRequired());
+ } else {
+ idpAttribute = new IdPAttribute(id);
+ }
+
+ idpAttribute.setValues(attributeValues);
+
+ return idpAttribute;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected Iterable<XMLObject> getValues(@Nonnull final Attribute input) {
+ return input.getAttributeValues();
+ }
+
+ /**
+ * A function to produce a "canonical" name for a SAML 2.0 {@link Attribute} for transcoding rules.
+ */
+ public static class NamingFunction implements Function<Attribute,String> {
+
+ /** {@inheritDoc} */
+ @Nullable public String apply(@Nullable final Attribute input) {
+
+ if (input == null || input.getName() == null) {
+ return null;
+ }
+
+ String format = input.getNameFormat();
+ if (format == null) {
+ format = Attribute.UNSPECIFIED;
+ }
+
+ final StringBuilder builder = new StringBuilder();
+ builder.append("SAML2:{").append(format).append('}').append(input.getName());
+ return builder.toString();
+ }
+
+ }
+
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..df99f1b
--- /dev/null
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAMLAttributeTranscoder.java
@@ -0,0 +1,285 @@
+/*
+ * 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.idp.saml.attribute.transcoding;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.AbstractAttributeTranscoder;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.xmlobject.ScopedValue;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.xml.DOMTypeSupport;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.schema.XSAny;
+import org.opensaml.core.xml.schema.XSBase64Binary;
+import org.opensaml.core.xml.schema.XSBoolean;
+import org.opensaml.core.xml.schema.XSDateTime;
+import org.opensaml.core.xml.schema.XSInteger;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.core.xml.schema.XSURI;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.common.SAMLObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base class for transcoders that support SAML attributes.
+ *
+ * @param <AttributeType> type of object produced
+ * @param <EncodedType> the type of data that can be handled by the transcoder
+ */
+public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAMLObject,
+ EncodedType extends IdPAttributeValue> extends AbstractAttributeTranscoder<AttributeType>
+ implements SAMLAttributeTranscoder<AttributeType> {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractSAMLAttributeTranscoder.class);
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable public AttributeType doEncode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends AttributeType> to,
+ @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
+
+ final String attributeId = attribute.getId();
+
+ log.debug("Beginning to encode attribute {}", attributeId);
+
+ final List<XMLObject> samlAttributeValues = new ArrayList<>();
+
+ for (final IdPAttributeValue o : attribute.getValues()) {
+ if (o == null) {
+ // filtered out upstream leave in test for sanity
+ log.debug("Skipping null value of attribute {}", attributeId);
+ continue;
+ }
+
+ if (!canEncodeValue(attribute, o)) {
+ log.warn("Skipping value of attribute '{}'; Type {} cannot be encoded by this encoder ({}).",
+ attributeId, o.getClass().getSimpleName(), this.getClass().getSimpleName());
+ continue;
+ }
+
+ final EncodedType attributeValue = (EncodedType) o;
+ final XMLObject samlAttributeValue =
+ encodeValue(profileRequestContext, attribute, rule, attributeValue);
+ if (samlAttributeValue == null) {
+ log.debug("Skipping null value for attribute {}", attributeId);
+ } else {
+ samlAttributeValues.add(samlAttributeValue);
+ }
+ }
+
+ log.debug("Encoded {} values for attribute {}", samlAttributeValues.size(), attributeId);
+ return buildAttribute(profileRequestContext, attribute, to, rule, samlAttributeValues);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable public IdPAttribute doDecode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final AttributeType input, @Nonnull final TranscodingRule rule)
+ throws AttributeDecodingException {
+
+ final String attributeName = getEncodedName(rule);
+
+ log.debug("Beginning to decode attribute {}", attributeName);
+
+ final List<IdPAttributeValue<?>> idpAttributeValues = new ArrayList<>();
+ final Iterable<XMLObject> samlAttributeValues = getValues(input);
+
+ for (final XMLObject o : samlAttributeValues) {
+ if (o == null) {
+ // filtered out upstream leave in test for sanity
+ log.debug("Skipping null value of attribute {}", attributeName);
+ continue;
+ }
+
+ final IdPAttributeValue<?> idpAttributeValue = decodeValue(profileRequestContext, input, rule, o);
+ if (idpAttributeValue == null) {
+ log.debug("Unable to decode value of attribute {}", attributeName);
+ } else {
+ idpAttributeValues.add(idpAttributeValue);
+ }
+ }
+
+ if (!idpAttributeValues.isEmpty()) {
+ log.debug("Decoded {} values for attribute {}", idpAttributeValues.size(), attributeName);
+ }
+ return buildIdPAttribute(profileRequestContext, input, rule, idpAttributeValues);
+ }
+
+ /**
+ * Function to return an XML object in string form.
+ *
+ * @param object object to decode
+ *
+ * @return decoded string, or null
+ */
+// Checkstyle: CyclomaticComplexity OFF
+ @Nullable protected String getStringValue(@Nonnull final XMLObject object) {
+ String retVal = null;
+
+ if (object instanceof XSString) {
+
+ retVal = ((XSString) object).getValue();
+
+ } else if (object instanceof XSURI) {
+
+ retVal = ((XSURI) object).getValue();
+
+ } else if (object instanceof XSBoolean) {
+
+ retVal = ((XSBoolean) object).getValue().getValue() ? "1" : "0";
+
+ } else if (object instanceof XSInteger) {
+
+ retVal = ((XSInteger) object).getValue().toString();
+
+ } else if (object instanceof XSDateTime) {
+
+ final Instant dt = ((XSDateTime) object).getValue();
+ if (dt != null) {
+ retVal = DOMTypeSupport.instantToString(dt);
+ } else {
+ retVal = null;
+ }
+
+ } else if (object instanceof XSBase64Binary) {
+
+ retVal = ((XSBase64Binary) object).getValue();
+
+ } else if (object instanceof ScopedValue) {
+
+ retVal = ((ScopedValue) object).getValue();
+
+ } else if (object instanceof XSAny) {
+
+ final XSAny wc = (XSAny) object;
+ if (wc.getUnknownAttributes().isEmpty() && wc.getUnknownXMLObjects().isEmpty()) {
+ retVal = wc.getTextContent();
+ } else {
+ retVal = null;
+ }
+ }
+
+ if (null == retVal) {
+ log.info("Value of type {} could not be converted", object.getClass().getSimpleName());
+ }
+ return retVal;
+ }
+// Checkstyle: CyclomaticComplexity ON
+
+ /**
+ * Checks if the given value can be handled by the transcoder.
+ *
+ * <p>In many cases this is simply a check to see if the given object is of the right type.</p>
+ *
+ * @param idpAttribute the attribute being encoded, never null
+ * @param value the value to check, never null
+ *
+ * @return true if the transcoder can encode this value, false if not
+ */
+ protected abstract boolean canEncodeValue(@Nonnull final IdPAttribute idpAttribute,
+ @Nonnull final IdPAttributeValue value);
+
+ /**
+ * Builds a SAML attribute element from the given attribute values.
+ *
+ * @param profileRequestContext current profile request
+ * @param attribute the attribute being encoded
+ * @param to target type to create
+ * @param rule properties to control encoding
+ * @param attributeValues the encoded values for the attribute
+ *
+ * @return the SAML attribute object
+ *
+ * @throws AttributeEncodingException thrown if there is a problem constructing the SAML attribute
+ */
+ @Nonnull protected abstract AttributeType buildAttribute(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nullable final IdPAttribute attribute,
+ @Nonnull final Class<? extends AttributeType> to, @Nonnull final TranscodingRule rule,
+ @Nonnull @NonnullElements final List<XMLObject> attributeValues) throws AttributeEncodingException;
+
+ /**
+ * Encodes an attribute value into a SAML AttributeValue element.
+ *
+ * @param profileRequestContext current profile request
+ * @param attribute the attribute being encoded
+ * @param rule properties to control encoding
+ * @param value the value to encode
+ *
+ * @return the attribute value or null if the resulting attribute value would be empty
+ *
+ * @throws AttributeEncodingException thrown if there is a problem encoding the attribute value
+ */
+ @Nullable protected abstract XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
+ @Nonnull final EncodedType value) throws AttributeEncodingException;
+
+ /**
+ * Builds an {@link IdPAttribute} from the given values.
+ *
+ * @param profileRequestContext current profile request
+ * @param attribute the attribute being decoded
+ * @param rule properties to control decoding
+ * @param attributeValues the decoded values for the attribute
+ *
+ * @return the IdPAttribute object
+ *
+ * @throws AttributeDecodingException thrown if there is a problem constructing the IdPAttribute
+ */
+ @Nonnull protected abstract IdPAttribute buildIdPAttribute(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeType attribute,
+ @Nonnull final TranscodingRule rule,
+ @Nonnull @NonnullElements final List<IdPAttributeValue<?>> attributeValues)
+ throws AttributeDecodingException;
+
+ /**
+ * Returns the values to decode from the concrete input object.
+ *
+ * @param input input object
+ *
+ * @return values to decode
+ */
+ @Nonnull protected abstract Iterable<XMLObject> getValues(@Nonnull final AttributeType input);
+
+ /**
+ * Function to decode a single {@link XMLObject} into an {@link IdPAttributeValue}.
+ *
+ * @param profileRequestContext current profile request
+ * @param attribute the attribute being decoded
+ * @param rule properties to control decoding
+ * @param value the value to decode
+ *
+ * @return the returned final {@link IdPAttributeValue} or null if decoding failed
+ */
+ @Nullable protected abstract IdPAttributeValue<?> decodeValue(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeType attribute,
+ @Nonnull final TranscodingRule rule, @Nullable final XMLObject value);
+
+}
\ No newline at end of file
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/attribute/mapping/impl/SAML1AttributeDesignatorMapper.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML1AttributeTranscoder.java
similarity index 61%
rename from idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML1AttributeDesignatorMapper.java
rename to idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML1AttributeTranscoder.java
index 990e0ce..0749595 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML1AttributeDesignatorMapper.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML1AttributeTranscoder.java
@@ -15,24 +15,25 @@
* limitations under the License.
*/
-package net.shibboleth.idp.saml.attribute.mapping.impl;
+package net.shibboleth.idp.saml.attribute.transcoding;
import javax.annotation.Nonnull;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeDesignatorMapper;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import org.opensaml.saml.saml1.core.Attribute;
import org.opensaml.saml.saml1.core.AttributeDesignator;
-/** A class that maps a SAML1 {@link AttributeDesignator} into an IdP {@link IdPAttribute}. */
-public class SAML1AttributeDesignatorMapper extends AbstractSAMLAttributeDesignatorMapper<IdPAttribute> {
-
- /** {@inheritDoc} */
- @Override
- @Nonnull protected IdPAttribute newAttribute(@Nonnull final AttributeDesignator input,
- @Nonnull @NotEmpty final String id) {
- return new IdPAttribute(id);
- }
-
+/**
+ * Marker interface for transcoders that operate on a SAML 1 {@link Attribute} or {@link AttributeDesignator}.
+ *
+ * @param <EncodedType> the type of data that can be handled by the transcoder
+ */
+public interface SAML1AttributeTranscoder<EncodedType extends IdPAttributeValue> extends
+ SAMLAttributeTranscoder<AttributeDesignator> {
+
+ /** The namespace of the attribute name. */
+ @Nonnull @NotEmpty static final String PROP_NAMESPACE = "namespace";
+
}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/SAML2AttributeEncoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML2AttributeTranscoder.java
similarity index 57%
rename from idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/SAML2AttributeEncoder.java
rename to idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML2AttributeTranscoder.java
index 98fdc4c..c36df8d 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/SAML2AttributeEncoder.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAML2AttributeTranscoder.java
@@ -15,33 +15,28 @@
* limitations under the License.
*/
-package net.shibboleth.idp.saml.attribute.encoding;
+package net.shibboleth.idp.saml.attribute.transcoding;
+
+import javax.annotation.Nonnull;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import org.opensaml.saml.saml2.core.Attribute;
-
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
/**
- * Interface for encoders that produce a SAML 2 {@link Attribute}.
+ * Marker interface for transcoders that operate on a SAML 2 {@link Attribute} or {@link RequestedAttribute}.
*
- * @param <EncodedType> the type of data that can be encoded by the encoder
+ * @param <EncodedType> the type of data that can be handled by the transcoder
*/
-public interface SAML2AttributeEncoder<EncodedType extends IdPAttributeValue> extends AttributeEncoder<Attribute> {
-
- /**
- * Get the encoded Name of the attribute.
- *
- * @return name of the attribute
- */
- @NonnullAfterInit String getName();
-
- /**
- * Get the encoded NameFormat of the attribute.
- *
- * @return name format of the attribute
- */
- @NonnullAfterInit String getNameFormat();
+public interface SAML2AttributeTranscoder<EncodedType extends IdPAttributeValue> extends
+ SAMLAttributeTranscoder<Attribute> {
+
+ /** A friendly, human readable, name for the attribute. */
+ @Nonnull @NotEmpty static final String PROP_FRIENDLY_NAME = "friendlyName";
+
+ /** The format of the attribute name. */
+ @Nonnull @NotEmpty static final String PROP_NAME_FORMAT = "nameFormat";
+
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML2AttributeMapper.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAMLAttributeTranscoder.java
similarity index 60%
rename from idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML2AttributeMapper.java
rename to idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAMLAttributeTranscoder.java
index 3c0f3cc..80a4404 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML2AttributeMapper.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAMLAttributeTranscoder.java
@@ -15,23 +15,26 @@
* limitations under the License.
*/
-package net.shibboleth.idp.saml.attribute.mapping.impl;
+package net.shibboleth.idp.saml.attribute.transcoding;
import javax.annotation.Nonnull;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import org.opensaml.saml.saml2.core.Attribute;
-
-/** A class that maps a SAML2 {@link Attribute} into an IdP {@link IdPAttribute}. */
-public class SAML2AttributeMapper extends AbstractSAMLAttributeMapper<Attribute, IdPAttribute> {
-
- /** {@inheritDoc} */
- @Override
- @Nonnull protected IdPAttribute newAttribute(@Nonnull final Attribute input, @Nonnull @NotEmpty final String id) {
- return new IdPAttribute(id);
- }
-
+import org.opensaml.saml.common.SAMLObject;
+
+/**
+ * Marker interface for transcoders that support SAML objects.
+ *
+ * @param <AttributeType> type of object produced
+ */
+public interface SAMLAttributeTranscoder<AttributeType extends SAMLObject> extends AttributeTranscoder<AttributeType> {
+
+ /** The attribute name. */
+ @Nonnull @NotEmpty static final String PROP_NAME = "name";
+
+ /** Whether to encode the xsi:type. */
+ @Nonnull @NotEmpty static final String PROP_ENCODE_TYPE = "encodeType";
+
}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/SAMLEncoderSupport.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAMLEncoderSupport.java
similarity index 99%
rename from idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/SAMLEncoderSupport.java
rename to idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAMLEncoderSupport.java
index b14649a..d299388 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/SAMLEncoderSupport.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/SAMLEncoderSupport.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package net.shibboleth.idp.saml.attribute.encoding;
+package net.shibboleth.idp.saml.attribute.transcoding;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/package-info.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/package-info.java
similarity index 83%
rename from idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/package-info.java
rename to idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/package-info.java
index 69b6f2e..4c9f4e9 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/encoding/package-info.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/package-info.java
@@ -16,7 +16,7 @@
*/
/**
- * Base classes for encoding {@link net.shibboleth.idp.attribute.IdPAttribute} objects into SAML message components.
+ * Base classes for SAML {@link net.shibboleth.idp.attribute.transcoding.AttributeTranscoder} classes.
*/
-package net.shibboleth.idp.saml.attribute.encoding;
\ No newline at end of file
+package net.shibboleth.idp.saml.attribute.transcoding;
\ No newline at end of file
diff --git a/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML1AttributeEncoderTest.java b/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML1AttributeEncoderTest.java
deleted file mode 100644
index 80e283f..0000000
--- a/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML1AttributeEncoderTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.xml.namespace.QName;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.XMLObjectBuilder;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml1.core.Attribute;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * Test for {@link AbstractSAML1AttributeEncoder}.
- */
-public class AbstractSAML1AttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- private XMLObjectBuilder<XSString> theBuilder;
-
- private QName theQName = new QName("LocalQNAME");
-
- private final String MY_NAME = "myName";
-
- private final String MY_NAMESPACE = "myNameSpace";
-
- private final String ATTRIBUTE_ID = "attrID";
-
- private final String ATTRIBUTE_VALUE_1 = "attrValOne";
-
- private final String ATTRIBUTE_VALUE_2 = "attrValueTwo";
-
- @BeforeClass public void initTest() throws ComponentInitializationException {
- theBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
-
- }
-
- @Test public void abstractSAML1AttributeEncoder() throws ComponentInitializationException, AttributeEncodingException {
- AbstractSAML1AttributeEncoder encoder = new AbstractSAMLAttributeEncoderTest.mockEncoder(theBuilder, theQName);
- encoder.setName(MY_NAME);
- encoder.setNamespace(MY_NAMESPACE);
- encoder.initialize();
- // Use literal here to catch things being edited by mistake
- Assert.assertEquals(encoder.getProtocol(), "urn:oasis:names:tc:SAML:1.1:protocol");
-
-
- IdPAttribute attr = new IdPAttribute(ATTRIBUTE_ID);
- attr.setValues(Arrays.asList(new StringAttributeValue(ATTRIBUTE_VALUE_1),
- new StringAttributeValue(ATTRIBUTE_VALUE_2)));
-
- XMLObject obj = encoder.encode(attr);
-
- Assert.assertTrue(obj instanceof Attribute);
-
- List<XMLObject> result = ((Attribute) obj).getAttributeValues();
-
- Assert.assertEquals(result.size(), 2);
- Set<String> resultSet = new HashSet<>(2);
- for (XMLObject o: result) {
- Assert.assertTrue(o instanceof XSString);
- resultSet.add(((XSString) o).getValue());
- }
- Assert.assertTrue(resultSet.contains(ATTRIBUTE_VALUE_1));
- Assert.assertTrue(resultSet.contains(ATTRIBUTE_VALUE_2));
- }
-}
diff --git a/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML2AttributeEncoderTest.java b/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML2AttributeEncoderTest.java
deleted file mode 100644
index d36bee4..0000000
--- a/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAML2AttributeEncoderTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.xml.namespace.QName;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.UnmodifiableComponentException;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.XMLObjectBuilder;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml2.core.Attribute;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * Test for {@link AbstractSAML2AttributeEncoder}.
- */
-public class AbstractSAML2AttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- private XMLObjectBuilder<XSString> theBuilder;
-
- private QName theQName = new QName("LocalQNAME");
-
- private final String MY_NAME = "myName";
-
- private final String MY_NAMESPACE = "myNameSpace";
-
- private final String ATTRIBUTE_ID = "attrID";
-
- private final String ATTRIBUTE_VALUE_1 = "attrValOne";
-
- private final String ATTRIBUTE_VALUE_2 = "attrValueTwo";
-
- private final String FRIENDLY_NAME = "friendly";
-
- @BeforeClass public void initTest() throws ComponentInitializationException {
- theBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
- }
-
- @Test public void abstractSAML2AttributeEncoder() throws ComponentInitializationException, AttributeEncodingException {
- AbstractSAML2AttributeEncoder encoder = new mockEncoder();
-
- encoder.setName(MY_NAME);
- encoder.setNameFormat(MY_NAMESPACE);
- encoder.setFriendlyName(FRIENDLY_NAME);
- encoder.initialize();
- // Use literal here to catch things being edited by mistake
- Assert.assertEquals(encoder.getProtocol(), "urn:oasis:names:tc:SAML:2.0:protocol");
-
-
- IdPAttribute attr = new IdPAttribute(ATTRIBUTE_ID);
- attr.setValues(Arrays.asList(new StringAttributeValue(ATTRIBUTE_VALUE_1),
- new StringAttributeValue(ATTRIBUTE_VALUE_2)));
-
- XMLObject obj = encoder.encode(attr);
-
- Assert.assertTrue(obj instanceof Attribute);
-
- List<XMLObject> result = ((Attribute) obj).getAttributeValues();
-
- Assert.assertEquals(result.size(), 2);
- Set<String> resultSet = new HashSet<>(2);
- for (XMLObject o: result) {
- Assert.assertTrue(o instanceof XSString);
- resultSet.add(((XSString) o).getValue());
- }
- Assert.assertTrue(resultSet.contains(ATTRIBUTE_VALUE_1));
- Assert.assertTrue(resultSet.contains(ATTRIBUTE_VALUE_2));
- }
-
- @Test public void friendlyName() throws ComponentInitializationException {
- AbstractSAML2AttributeEncoder encoder = new mockEncoder();
- Assert.assertNull(encoder.getFriendlyName());
- encoder.setName(MY_NAME);
- encoder.setNameFormat(MY_NAMESPACE);
- encoder.initialize();
-
- encoder = new mockEncoder();
- Assert.assertNull(encoder.getFriendlyName());
- encoder.setName(MY_NAME);
- encoder.setFriendlyName(FRIENDLY_NAME);
- encoder.setNameFormat(MY_NAMESPACE);
- Assert.assertEquals(encoder.getFriendlyName(), FRIENDLY_NAME);
- encoder.initialize();
- Assert.assertEquals(encoder.getFriendlyName(), FRIENDLY_NAME);
- try {
- encoder.setFriendlyName(FRIENDLY_NAME);
- Assert.fail();
- } catch (UnmodifiableComponentException ex) {
- //OK
- }
- }
-
- protected class mockEncoder extends AbstractSAML2AttributeEncoder {
-
- /** {@inheritDoc} */
- protected boolean canEncodeValue(IdPAttribute attribute, IdPAttributeValue value) {
- return ! (value instanceof ByteAttributeValue);
- }
-
- /** {@inheritDoc} */
- protected XMLObject encodeValue(IdPAttribute attribute, IdPAttributeValue value) throws AttributeEncodingException {
- if (!(value instanceof StringAttributeValue)) {
- return null;
- }
- XSString result = theBuilder.buildObject(theQName);
- result.setValue((String) value.getValue());
- return result;
- }
-
- }
-
-}
diff --git a/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAMLAttributeEncoderTest.java b/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAMLAttributeEncoderTest.java
deleted file mode 100644
index 68ffd84..0000000
--- a/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/AbstractSAMLAttributeEncoderTest.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.xml.namespace.QName;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.UninitializedComponentException;
-import net.shibboleth.utilities.java.support.component.UnmodifiableComponentException;
-import net.shibboleth.utilities.java.support.logic.ConstraintViolationException;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.XMLObjectBuilder;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml1.core.Attribute;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- *
- */
-public class AbstractSAMLAttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- private XMLObjectBuilder<XSString> theBuilder;
- private QName theQName = new QName("LocalQNAME");
- private final String MY_NAME = "myName";
- private final String MY_NAMESPACE = "myNameSpace";
- private final String ATTRIBUTE_ID = "attrID";
- private final String ATTRIBUTE_VALUE_1 = "attrValOne";
- private final String ATTRIBUTE_VALUE_2 = "attrValeTwo";
-
- @BeforeClass public void initTest() throws ComponentInitializationException {
- theBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
- }
-
- @Test public void initializeAndSetters() throws AttributeEncodingException, ComponentInitializationException {
- AbstractSAML1AttributeEncoder encoder = new mockEncoder(theBuilder, theQName);
-
- Assert.assertNull(encoder.getName());
- Assert.assertEquals(encoder.getNamespace(), "urn:mace:shibboleth:1.0:attributeNamespace:uri");
-
- try {
- encoder.setName("");
- Assert.fail();
- } catch (ConstraintViolationException e) {
-
- }
-
- encoder = new mockEncoder(theBuilder, theQName);
- try {
- encoder.setNamespace("");
- Assert.fail();
- } catch (ConstraintViolationException e) {
-
- }
-
- encoder = new mockEncoder(theBuilder, theQName);
- encoder.setNamespace(MY_NAMESPACE);
- encoder.setName(MY_NAME);
-
- try {
- encoder.encode(new IdPAttribute(ATTRIBUTE_ID));
- Assert.fail();
- } catch (UninitializedComponentException ex) {
- // OK
- }
-
- encoder.initialize();
- try {
- encoder.setName(" ");
- Assert.fail();
- } catch (UnmodifiableComponentException ex) {
- //
- }
-
- try {
- encoder.setNamespace(" ");
- Assert.fail();
- } catch (UnmodifiableComponentException ex) {
- //
- }
-
- }
-
- @Test public void encode() throws AttributeEncodingException, ComponentInitializationException {
- AbstractSAML1AttributeEncoder encoder = new mockEncoder(theBuilder, theQName);
- encoder.setNamespace(MY_NAMESPACE);
- encoder.setName(MY_NAME);
- encoder.initialize();
- IdPAttribute attr = new IdPAttribute(ATTRIBUTE_ID);
-
- try {
- encoder.encode(attr);
- } catch (AttributeEncodingException e) {
- // OK
- }
-
- final int[] intArray = {1, 2, 3, 4};
- final List<IdPAttributeValue<?>> values = new ArrayList<>(
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
- null,
- new IdPAttributeValue<Object>() {
- @Override
- public Object getValue() {
- return intArray;
- }
-
- @Override
- public String getDisplayValue() {
- return intArray.toString();
- }
- }
- ));
- attr.setValues(values);
- try {
- encoder.encode(attr);
- } catch (AttributeEncodingException e) {
- // OK
- }
- values.add(new StringAttributeValue(ATTRIBUTE_VALUE_1));
- values.add(new StringAttributeValue(ATTRIBUTE_VALUE_2));
- attr.setValues(values);
-
- List<XMLObject> result = ((Attribute) encoder.encode(attr)).getAttributeValues();
-
- Assert.assertEquals(result.size(), 2);
- Set<String> resultSet = new HashSet<>(2);
- for (XMLObject o: result) {
- Assert.assertTrue(o instanceof XSString);
- resultSet.add(((XSString) o).getValue());
- }
- Assert.assertTrue(resultSet.contains(ATTRIBUTE_VALUE_1));
- Assert.assertTrue(resultSet.contains(ATTRIBUTE_VALUE_2));
-
- }
-
- @Test public void equalsHash() {
- mockEncoder enc1 = new mockEncoder(theBuilder, theQName);
- Assert.assertEquals(enc1, enc1);
- Assert.assertNotSame(enc1, null);
- Assert.assertNotSame(enc1, this);
-
- mockEncoder enc2 = new mockEncoder(theBuilder, theQName);
-
- Assert.assertEquals(enc1, enc2);
- Assert.assertEquals(enc1.hashCode(), enc2.hashCode());
- enc1.setName(MY_NAME);
- enc1.setNamespace(MY_NAMESPACE);
- enc2.setName(MY_NAME);
- enc2.setNamespace(MY_NAMESPACE);
- Assert.assertEquals(enc1, enc2);
- Assert.assertEquals(enc1.hashCode(), enc2.hashCode());
- enc2.setName(MY_NAME + MY_NAME);
- Assert.assertNotSame(enc1, enc2);
- Assert.assertNotSame(enc1.hashCode(), enc2.hashCode());
- enc2.setName(MY_NAME);
- enc2.setNamespace(MY_NAME);
- Assert.assertNotSame(enc1, enc2);
- Assert.assertNotSame(enc1.hashCode(), enc2.hashCode());
- }
-
- protected static class mockEncoder extends AbstractSAML1AttributeEncoder {
-
- @Nonnull private final XMLObjectBuilder<XSString> builder;
- @Nonnull private final QName myQName;
-
- /**
- * Constructor.
- *
- * @param theBuilder
- * @param theQName
- */
- public mockEncoder(@Nonnull final XMLObjectBuilder<XSString> theBuilder, @Nonnull final QName theQName) {
- builder = theBuilder;
- myQName = theQName;
- }
-
- /** {@inheritDoc} */
- @Override
- protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final IdPAttributeValue value) {
- return ! (value instanceof ByteAttributeValue);
- }
-
- /** {@inheritDoc} */
- @Override
- @Nullable protected XMLObject encodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final IdPAttributeValue value) throws AttributeEncodingException {
- if (!(value instanceof StringAttributeValue)) {
- return null;
- }
- XSString result = builder.buildObject(myQName);
- result.setValue((String) value.getValue());
- return result;
- }
-
- }
-}
diff --git a/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/SAMLEncoderSupportTest.java b/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/SAMLEncoderSupportTest.java
similarity index 99%
rename from idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/SAMLEncoderSupportTest.java
rename to idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/SAMLEncoderSupportTest.java
index 9a9cb82..759e563 100644
--- a/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/encoding/SAMLEncoderSupportTest.java
+++ b/idp-saml-api/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/SAMLEncoderSupportTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package net.shibboleth.idp.saml.attribute.encoding;
+package net.shibboleth.idp.saml.attribute.transcoding;
import java.util.List;
diff --git a/idp-saml-impl/.project b/idp-saml-impl/.project
index 1b5d236..a9a4b04 100644
--- a/idp-saml-impl/.project
+++ b/idp-saml-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ByteAttributeEncoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ByteAttributeEncoder.java
deleted file mode 100644
index 3e53911..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ByteAttributeEncoder.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.saml.attribute.encoding.AbstractSAML1AttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.SAMLEncoderSupport;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.saml1.core.AttributeValue;
-
-/**
- * {@link net.shibboleth.idp.attribute.AttributeEncoder} that produces SAML 1 attributes from an
- * {@link IdPAttribute} that contains <code>byte[]</code> values.
- */
-public class SAML1ByteAttributeEncoder extends AbstractSAML1AttributeEncoder<ByteAttributeValue> {
-
- /** {@inheritDoc} */
- @Override
- protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute, @Nonnull final IdPAttributeValue value) {
- return value instanceof ByteAttributeValue;
- }
-
- /** {@inheritDoc} */
- @Override
- @Nullable protected XMLObject encodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final ByteAttributeValue value) throws AttributeEncodingException {
- return SAMLEncoderSupport.encodeByteArrayValue(attribute,
- AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(), encodeType());
- }
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ScopedStringAttributeEncoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ScopedStringAttributeEncoder.java
deleted file mode 100644
index 8912aa1..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ScopedStringAttributeEncoder.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.saml.attribute.encoding.AbstractSAML1AttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.SAMLEncoderSupport;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.saml1.core.AttributeValue;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * {@link net.shibboleth.idp.attribute.AttributeEncoder} that produces SAML 1 attributes from an
- * {@link net.shibboleth.idp.attribute.IdPAttribute} that contains scoped string values.
- */
-public class SAML1ScopedStringAttributeEncoder extends AbstractSAML1AttributeEncoder<ScopedStringAttributeValue> {
-
- /** The log. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1ScopedStringAttributeEncoder.class);
-
- /** Type of scoping to use. */
- @Nullable private String scopeType;
-
- /** Delimiter used for "inline" scopeType. */
- @Nullable private String scopeDelimiter;
-
- /** Attribute name used for "attribute" scopeType. */
- @Nullable private String scopeAttributeName;
-
- /**
- * Constructor.
- *
- */
- public SAML1ScopedStringAttributeEncoder() {
- scopeDelimiter = "@";
- scopeAttributeName = "Scope";
- scopeType = "attribute";
-
- // Turn off type encoding, because we default to a non-built-in type that consumers won't
- // have the schema for.
- setEncodeType(false);
- }
-
- /**
- * Get the name of the non-inline scope-carrying attribute.
- *
- * @return the name of the scope-carrying attribute
- */
- @Nullable public String getScopeAttributeName() {
- return scopeAttributeName;
- }
-
- /**
- * Get the scope delimiter.
- *
- * @return the scope delimiter
- */
- @Nullable public String getScopeDelimiter() {
- return scopeDelimiter;
- }
-
- /**
- * Get the scope syntax type.
- *
- * @return the type of scope syntax to use
- */
- @Nullable public String getScopeType() {
- return scopeType;
- }
-
- /**
- * Set the name of the non-inline scope-carrying attribute.
- *
- * @param newScopeAttribute the name to set
- */
- public void setScopeAttributeName(@Nullable final String newScopeAttribute) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- scopeAttributeName = StringSupport.trimOrNull(newScopeAttribute);
- }
-
- /**
- * Set the scope delimiter.
- *
- * @param newScopeDelimiter delimiter to set
- */
- public void setScopeDelimiter(@Nullable final String newScopeDelimiter) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- scopeDelimiter = StringSupport.trimOrNull(newScopeDelimiter);
- }
-
- /**
- * Set the scope syntax type.
- *
- * @param newScopeType the scope syntax type
- */
- public void setScopeType(@Nullable final String newScopeType) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- scopeType = StringSupport.trimOrNull(newScopeType);
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
-
- if (null == getScopeType()) {
- log.debug("Scope type not set, assuming \"attribute\"");
- scopeType = "attribute";
- }
-
- if ("attribute".equals(getScopeType())) {
- if (null == getScopeAttributeName()) {
- throw new ComponentInitializationException(
- "Encoder of type \"attribute\" must specify a scope attribute name");
- }
- } else if ("inline".equals(getScopeType())) {
- if (null == getScopeDelimiter()) {
- throw new ComponentInitializationException("Encoder of type \"inline\" must specify a scope delimiter");
- }
- } else {
- throw new ComponentInitializationException("Encoder scope type must be set to \"inline\" or \"attribute\"");
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute, @Nonnull final IdPAttributeValue value) {
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
-
- return value instanceof ScopedStringAttributeValue;
- }
-
- /** {@inheritDoc} */
- @Override
- @Nullable protected XMLObject encodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final ScopedStringAttributeValue value) throws AttributeEncodingException {
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
-
- if ("attribute".equals(getScopeType())) {
- return SAMLEncoderSupport.encodeScopedStringValueAttribute(attribute,
- AttributeValue.DEFAULT_ELEMENT_NAME, value, getScopeAttributeName(), encodeType());
- } else {
- return SAMLEncoderSupport.encodeScopedStringValueInline(attribute,
- AttributeValue.DEFAULT_ELEMENT_NAME, value, getScopeDelimiter(), encodeType());
- }
- }
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1XMLObjectAttributeEncoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1XMLObjectAttributeEncoder.java
deleted file mode 100644
index e1ce07d..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1XMLObjectAttributeEncoder.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
-import net.shibboleth.idp.saml.attribute.encoding.AbstractSAML1AttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.SAMLEncoderSupport;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.saml1.core.AttributeValue;
-
-/**
- * {@link net.shibboleth.idp.attribute.AttributeEncoder} that produces SAML 1 attributes from an
- * {@link net.shibboleth.idp.attribute.IdPAttribute} that contains {@link XMLObjectAttributeValue} values.
- */
-public class SAML1XMLObjectAttributeEncoder extends AbstractSAML1AttributeEncoder<XMLObjectAttributeValue> {
-
- /** {@inheritDoc} */
- @Override
- protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute, @Nonnull final IdPAttributeValue value) {
- return value instanceof XMLObjectAttributeValue;
- }
-
- /** {@inheritDoc} */
- @Override
- @Nullable protected XMLObject encodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final XMLObjectAttributeValue value) throws AttributeEncodingException {
- return SAMLEncoderSupport.encodeXMLObjectValue(attribute,
- AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue());
- }
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ByteAttributeEncoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ByteAttributeEncoder.java
deleted file mode 100644
index 1350f84..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ByteAttributeEncoder.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.idp.saml.attribute.encoding.AbstractSAML2AttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.AttributeMapperProcessor;
-import net.shibboleth.idp.saml.attribute.encoding.SAMLEncoderSupport;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.ByteAttributeValueMapper;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.saml2.core.AttributeValue;
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
-
-/**
- * {@link net.shibboleth.idp.attribute.AttributeEncoder} that produces a SAML 2 Attribute from an {@link IdPAttribute}
- * that contains <code>byte[]</code> values.
- */
-public class SAML2ByteAttributeEncoder extends AbstractSAML2AttributeEncoder<ByteAttributeValue> implements
- AttributeMapperProcessor<RequestedAttribute, IdPRequestedAttribute> {
-
- /** {@inheritDoc} */
- @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final IdPAttributeValue value) {
- return value instanceof ByteAttributeValue;
- }
-
- /** {@inheritDoc} */
- @Override @Nullable protected XMLObject encodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final ByteAttributeValue value) throws AttributeEncodingException {
- return SAMLEncoderSupport.encodeByteArrayValue(attribute,
- AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(), encodeType());
- }
-
- /** {@inheritDoc} */
- @Override @Nonnull public void populateAttributeMapper(final
- AbstractSAMLAttributeMapper<RequestedAttribute, IdPRequestedAttribute> mapper) {
- mapper.setAttributeFormat(getNameFormat());
- mapper.setId(getMapperId());
- mapper.setSAMLName(getName());
- mapper.setValueMapper(new ByteAttributeValueMapper());
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ScopedStringAttributeEncoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ScopedStringAttributeEncoder.java
deleted file mode 100644
index 8156190..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ScopedStringAttributeEncoder.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.saml.attribute.encoding.AbstractSAML2AttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.AttributeMapperProcessor;
-import net.shibboleth.idp.saml.attribute.encoding.SAMLEncoderSupport;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.ScopedStringAttributeValueMapper;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.saml2.core.AttributeValue;
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * {@link net.shibboleth.idp.attribute.AttributeEncoder} that produces a SAML 2 Attribute from an
- * {@link net.shibboleth.idp.attribute.IdPAttribute} that contains scoped string values.
- */
-public class SAML2ScopedStringAttributeEncoder extends AbstractSAML2AttributeEncoder<ScopedStringAttributeValue>
- implements AttributeMapperProcessor<RequestedAttribute, IdPRequestedAttribute> {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(SAML2ScopedStringAttributeEncoder.class);
-
- /** Type of scoping to use. */
- @Nullable private String scopeType;
-
- /** Delimiter used for "inline" scopeType. */
- @Nullable private String scopeDelimiter;
-
- /** Attribute name used for "attribute" scopeType. */
- @Nullable private String scopeAttributeName;
-
- /**
- * Constructor.
- *
- */
- public SAML2ScopedStringAttributeEncoder() {
- scopeDelimiter = "@";
- scopeAttributeName = "Scope";
- scopeType = "inline";
- }
-
- /**
- * Get the name of the non-inline scope-carrying attribute.
- *
- * @return the name of the scope-carrying attribute
- */
- @Nullable public String getScopeAttributeName() {
- return scopeAttributeName;
- }
-
- /**
- * Get the scope delimiter.
- *
- * @return the scope delimiter
- */
- @Nullable public String getScopeDelimiter() {
- return scopeDelimiter;
- }
-
- /**
- * Get the scope syntax type.
- *
- * @return the type of scope syntax to use
- */
- @Nullable public String getScopeType() {
- return scopeType;
- }
-
- /**
- * Set the name of the non-inline scope-carrying attribute.
- *
- * @param newScopeAttribute the name to set
- */
- public void setScopeAttributeName(@Nullable final String newScopeAttribute) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- scopeAttributeName = StringSupport.trimOrNull(newScopeAttribute);
- }
-
- /**
- * Set the scope delimiter.
- *
- * @param newScopeDelimiter delimiter to set
- */
- public void setScopeDelimiter(@Nullable final String newScopeDelimiter) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- scopeDelimiter = StringSupport.trimOrNull(newScopeDelimiter);
- }
-
- /**
- * Set the scope syntax type.
- *
- * @param newScopeType the scope syntax type
- */
- public void setScopeType(@Nullable final String newScopeType) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- scopeType = StringSupport.trimOrNull(newScopeType);
- }
-
- /**
- * Ensures that the values we will need are all there.
- *
- * {@inheritDoc}
- */
- @Override protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
-
- if (null == getScopeType()) {
- log.debug("Scope type not set, assuming \"inline\"");
- scopeType = "inline";
- }
-
- if ("attribute".equals(getScopeType())) {
- if (null == getScopeAttributeName()) {
- throw new ComponentInitializationException(
- "Encoder of type \"attribute\" must specify a scope attribute name");
- }
- } else if ("inline".equals(getScopeType())) {
- if (null == getScopeDelimiter()) {
- throw new ComponentInitializationException("Encoder of type \"inline\" must specify a scope delimiter");
- }
- } else {
- throw new ComponentInitializationException("Encoder scope type must be set to \"inline\" or \"attribute\"");
- }
- }
-
- /** {@inheritDoc} */
- @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final IdPAttributeValue value) {
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
-
- return value instanceof ScopedStringAttributeValue;
- }
-
- /** {@inheritDoc} */
- @Override @Nullable protected XMLObject encodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final ScopedStringAttributeValue value) throws AttributeEncodingException {
- ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
-
- if ("attribute".equals(getScopeType())) {
- return SAMLEncoderSupport.encodeScopedStringValueAttribute(attribute,
- AttributeValue.DEFAULT_ELEMENT_NAME, value, getScopeAttributeName(), encodeType());
- } else {
- return SAMLEncoderSupport.encodeScopedStringValueInline(
- attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value, getScopeDelimiter(), encodeType());
- }
- }
-
- /** {@inheritDoc} */
- @Override @Nonnull public void populateAttributeMapper(
- final AbstractSAMLAttributeMapper<RequestedAttribute, IdPRequestedAttribute> mapper) {
- mapper.setAttributeFormat(getNameFormat());
- mapper.setId(getMapperId());
- mapper.setSAMLName(getName());
- final ScopedStringAttributeValueMapper foo = new ScopedStringAttributeValueMapper();
- foo.setDelimiter(getScopeDelimiter());
- mapper.setValueMapper(foo);
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2XMLObjectAttributeEncoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2XMLObjectAttributeEncoder.java
deleted file mode 100644
index 097a035..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2XMLObjectAttributeEncoder.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
-import net.shibboleth.idp.saml.attribute.encoding.AbstractSAML2AttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.AttributeMapperProcessor;
-import net.shibboleth.idp.saml.attribute.encoding.SAMLEncoderSupport;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.XMLObjectAttributeValueMapper;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.saml2.core.AttributeValue;
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
-
-/**
- * {@link net.shibboleth.idp.attribute.AttributeEncoder} that produces a SAML 2 Attribute from an {@link IdPAttribute}
- * that contains {@link XMLObject} values.
- */
-public class SAML2XMLObjectAttributeEncoder extends AbstractSAML2AttributeEncoder<XMLObjectAttributeValue> implements
- AttributeMapperProcessor<RequestedAttribute, IdPRequestedAttribute> {
-
- /** {@inheritDoc} */
- @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final IdPAttributeValue value) {
- return value instanceof XMLObjectAttributeValue;
- }
-
- /** {@inheritDoc} */
- @Override @Nullable protected XMLObject encodeValue(@Nonnull final IdPAttribute attribute,
- @Nonnull final XMLObjectAttributeValue value) throws AttributeEncodingException {
- return SAMLEncoderSupport
- .encodeXMLObjectValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue());
- }
-
- /** {@inheritDoc} */
- @Override @Nonnull public void populateAttributeMapper(
- final AbstractSAMLAttributeMapper<RequestedAttribute, IdPRequestedAttribute> mapper) {
-
- mapper.setAttributeFormat(getNameFormat());
- mapper.setId(getMapperId());
- mapper.setSAMLName(getName());
- mapper.setValueMapper(new XMLObjectAttributeValueMapper());
-
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/ByteAttributeValueMapper.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/ByteAttributeValueMapper.java
deleted file mode 100644
index 55fd0aa..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/ByteAttributeValueMapper.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeValueMapper;
-import net.shibboleth.utilities.java.support.codec.Base64Support;
-
-import org.opensaml.core.xml.XMLObject;
-
-/**
- * Mapping extract a {@link ByteAttributeValue} from an AttributeValue.
- */
-public class ByteAttributeValueMapper extends AbstractSAMLAttributeValueMapper {
-
- /** {@inheritDoc} */
- @Nullable protected IdPAttributeValue<?> decodeValue(@Nonnull final XMLObject object) {
- final String value = getStringValue(object);
- if (null == value) {
- return null;
- }
- final byte[] decoded = Base64Support.decode(value);
- if (null == decoded) {
- return null;
- }
- return ByteAttributeValue.valueOf(decoded);
- }
-
- /** {@inheritDoc} */
- @Nonnull protected String getAttributeTypeName() {
- return "Base64Encoded";
- }
-}
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributeMapper.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributeMapper.java
deleted file mode 100644
index e6227f3..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributeMapper.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
-
-/** A class that maps a SAML2 {@link RequestedAttribute} into an IdP {@link IdPRequestedAttribute}. */
-public class RequestedAttributeMapper extends AbstractSAMLAttributeMapper<RequestedAttribute, IdPRequestedAttribute> {
-
- /** {@inheritDoc} */
- @Override
- @Nonnull protected IdPRequestedAttribute newAttribute(@Nonnull final RequestedAttribute input,
- @Nonnull @NotEmpty final String id) {
- final IdPRequestedAttribute output = new IdPRequestedAttribute(id);
- output.setRequired(input.isRequired());
- return output;
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributesMapper.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributesMapper.java
deleted file mode 100644
index d5affc5..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributesMapper.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributesMapper;
-
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
-
-import com.google.common.base.Supplier;
-
-/**
- * This class conceptually represents the content of a attribute-map file, hence it describes (and then does) the
- * mappings from a {@link java.util.List} of SAML2 {@link RequestedAttribute} into a
- * {@link com.google.common.collect.Multimap} going from (SAML2) attributeId to {@link IdPRequestedAttribute}s.
- *
- */
-public class RequestedAttributesMapper extends AbstractSAMLAttributesMapper<RequestedAttribute, IdPRequestedAttribute> {
-
- /** Default constructor. */
- public RequestedAttributesMapper() {
-
- }
-
- /**
- * Generate a specific mapper to go from {@link RequestedAttribute} to {@link IdPRequestedAttribute} by inverting
- * the function of the mappers in the profiled {@link AttributeResolver}.
- *
- * @param resolver resolver to invert
- */
- public RequestedAttributesMapper(@Nonnull final AttributeResolver resolver) {
- super(resolver, "RequestedMapper<" + resolver.getId() + ">",
- new Supplier<AbstractSAMLAttributeMapper<RequestedAttribute, IdPRequestedAttribute>>() {
-
- @Override public RequestedAttributeMapper get() {
- return new RequestedAttributeMapper();
- }
- });
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML1AttributeDesignatorsMapper.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML1AttributeDesignatorsMapper.java
deleted file mode 100644
index bb3348a..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML1AttributeDesignatorsMapper.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeDesignatorMapper;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeDesignatorsMapper;
-
-import com.google.common.base.Supplier;
-
-/**
- * This class conceptually represents the content of a attribute-map file, hence it describes (and then does) the
- * mappings from a {@link java.util.List} of SAML1 {@link org.opensaml.saml.saml1.core.AttributeDesignator} into a
- * {@link com.google.common.collect.Multimap} going from (SAML1) attributeId to {@link IdPAttribute}s.
- *
- */
-public class SAML1AttributeDesignatorsMapper extends AbstractSAMLAttributeDesignatorsMapper<IdPAttribute> {
-
- /** Default constructor. */
- public SAML1AttributeDesignatorsMapper() {
-
- }
-
- /**
- * Generate a specific mapper to go from {@link org.opensaml.saml.saml1.core.AttributeDesignator} to
- * {@link IdPAttribute} by inverting the function of the mappers in the profiled {@link AttributeResolver}.
- *
- * @param resolver resolver to invert
- */
- public SAML1AttributeDesignatorsMapper(@Nonnull final AttributeResolver resolver) {
- super(resolver, "Mapper<" + resolver.getId() + ">",
- new Supplier<AbstractSAMLAttributeDesignatorMapper<IdPAttribute>>() {
-
- @Override public SAML1AttributeDesignatorMapper get() {
- return new SAML1AttributeDesignatorMapper();
- }
- });
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML1AttributeDesignatorsMapperService.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML1AttributeDesignatorsMapperService.java
deleted file mode 100644
index cc44d99..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML1AttributeDesignatorsMapperService.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import java.time.Instant;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.ThreadSafe;
-
-import org.opensaml.saml.saml1.core.AttributeDesignator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Multimap;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapper;
-import net.shibboleth.utilities.java.support.annotation.ParameterName;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.service.ReloadableService;
-import net.shibboleth.utilities.java.support.service.ServiceableComponent;
-
-/**
- * An implementation of {@link SAML1AttributeDesignatorsMapper} for use by objects that
- * can't just store a constructed mapper themselves, such as action beans.
- */
- at ThreadSafe
-public class SAML1AttributeDesignatorsMapperService implements AttributesMapper<AttributeDesignator,IdPAttribute> {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1AttributeDesignatorsMapperService.class);
-
- /** Service used to get the resolver used to fetch attributes. */
- @Nonnull private final ReloadableService<AttributeResolver> attributeResolverService;
-
- /** Whether the last invocation of {@link ReloadableService#reload()}
- * on {@link #attributeResolverService} failed. This limits the noise in log file. */
- @Nonnull private boolean captiveServiceReloadFailed;
-
- /** Cached AttributeMapper. */
- @Nullable private SAML1AttributeDesignatorsMapper attributesMapper;
-
- /** Date when the cache was last refreshed. */
- @Nullable private Instant lastReload;
-
- /**
- * Constructor.
- *
- * @param resolverService the service for the attribute resolver we are to derive mapping info from
- */
- public SAML1AttributeDesignatorsMapperService(
- @Nonnull @ParameterName(name="resolverService")
- final ReloadableService<AttributeResolver> resolverService) {
- attributeResolverService = Constraint.isNotNull(resolverService, "AttributeResolver cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override
- @Nonnull @NonnullElements public Multimap<String, IdPAttribute> mapAttributes(
- @Nonnull @NonnullElements final List<AttributeDesignator> prototypes) {
-
- final SAML1AttributeDesignatorsMapper mapper = getMapper();
- if (null == mapper) {
- log.error("No AttributeMapper available, returning nothing");
- return ArrayListMultimap.create();
- }
-
- return mapper.mapAttributes(prototypes);
- }
-
- /**
- * Check to see if a reload of the mapper is required and do so, and return whatever should be used.
- *
- * @return the mapper to use
- */
- @Nullable private SAML1AttributeDesignatorsMapper getMapper() {
-
- if (lastReload != null && lastReload.equals(attributeResolverService.getLastSuccessfulReloadInstant())) {
- // Nothing has changed since we last reloaded.
- return attributesMapper;
- }
-
- // Reload.
- ServiceableComponent<AttributeResolver> component = null;
- SAML1AttributeDesignatorsMapper am = 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 (!captiveServiceReloadFailed) {
- log.error("Invalid AttributeResolver configuration");
- }
- captiveServiceReloadFailed = true;
- } else {
- final AttributeResolver attributeResolver = component.getComponent();
- am = new SAML1AttributeDesignatorsMapper(attributeResolver);
- captiveServiceReloadFailed = false;
- lastReload = when;
- }
- } finally {
- if (null != component) {
- component.unpinComponent();
- }
- }
-
- try {
- if (null != am) {
- am.initialize();
- }
- } catch (final ComponentInitializationException e) {
- log.error("Error initializing AttributeMapper", e);
- }
-
- attributesMapper = am;
- return am;
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML2AttributesMapper.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML2AttributesMapper.java
deleted file mode 100644
index cbaea518..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML2AttributesMapper.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributesMapper;
-
-import org.opensaml.saml.saml2.core.Attribute;
-
-import com.google.common.base.Supplier;
-
-/**
- * This class conceptually represents the content of a attribute-map file, hence it describes (and then does) the
- * mappings from a {@link java.util.List} of SAML2 {@link Attribute} into a {@link com.google.common.collect.Multimap}
- * going from (SAML2) attributeId to {@link IdPAttribute}s.
- *
- */
-public class SAML2AttributesMapper extends AbstractSAMLAttributesMapper<Attribute, IdPAttribute> {
-
- /** Default constructor. */
- public SAML2AttributesMapper() {
-
- }
-
- /**
- * Generate a specific mapper to go from {@link Attribute} to {@link IdPAttribute} by inverting
- * the function of the mappers in the profiled {@link AttributeResolver}.
- *
- * @param resolver resolver to invert
- */
- public SAML2AttributesMapper(@Nonnull final AttributeResolver resolver) {
- super(resolver, "Mapper<" + resolver.getId() + ">",
- new Supplier<AbstractSAMLAttributeMapper<Attribute, IdPAttribute>>() {
-
- @Override public SAML2AttributeMapper get() {
- return new SAML2AttributeMapper();
- }
- });
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML2AttributesMapperService.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML2AttributesMapperService.java
deleted file mode 100644
index bc30707..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/SAML2AttributesMapperService.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import java.time.Instant;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.ThreadSafe;
-
-import org.opensaml.saml.saml2.core.Attribute;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Multimap;
-
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.resolver.AttributeResolver;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapper;
-import net.shibboleth.utilities.java.support.annotation.ParameterName;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.service.ReloadableService;
-import net.shibboleth.utilities.java.support.service.ServiceableComponent;
-
-/**
- * An implementation of {@link SAML2AttributesMapper} for use by objects that can't just store a constructed mapper
- * themselves, such as action beans.
- */
- at ThreadSafe
-public class SAML2AttributesMapperService implements AttributesMapper<Attribute, IdPAttribute> {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(SAML2AttributesMapperService.class);
-
- /** Service used to get the resolver used to fetch attributes. */
- @Nonnull private final ReloadableService<AttributeResolver> attributeResolverService;
-
- /** Whether the last invocation of {@link ReloadableService#reload()}
- * on {@link #attributeResolverService} failed. This limits the noise in log file. */
- @Nonnull private boolean captiveServiceReloadFailed;
-
- /** Cached AttributeMapper. */
- @Nullable private SAML2AttributesMapper attributesMapper;
-
- /** Date when the cache was last refreshed. */
- @Nullable private Instant lastReload;
-
- /**
- * Constructor.
- *
- * @param resolverService the service for the attribute resolver we are to derive mapping info from
- */
- public SAML2AttributesMapperService(@Nonnull @ParameterName(name="resolverService")
- final ReloadableService<AttributeResolver> resolverService) {
- attributeResolverService = Constraint.isNotNull(resolverService, "AttributeResolver cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override @Nonnull @NonnullElements public Multimap<String, IdPAttribute> mapAttributes(
- @Nonnull @NonnullElements final List<Attribute> prototypes) {
-
- final SAML2AttributesMapper mapper = getMapper();
- if (null == mapper) {
- log.error("No AttributeMapper available, returning nothing");
- return ArrayListMultimap.create();
- }
-
- return mapper.mapAttributes(prototypes);
- }
-
- /**
- * Check to see if a reload of the mapper is required and do so, and return whatever should be used.
- *
- * @return the mapper to use
- */
- @Nullable private SAML2AttributesMapper getMapper() {
-
- if (lastReload != null && lastReload.equals(attributeResolverService.getLastSuccessfulReloadInstant())) {
- // Nothing has changed since we last reloaded.
- return attributesMapper;
- }
-
- // Reload.
- ServiceableComponent<AttributeResolver> component = null;
- SAML2AttributesMapper am = 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 (!captiveServiceReloadFailed) {
- log.error("Invalid AttributeResolver configuration");
- }
- captiveServiceReloadFailed = true;
- } else {
- final AttributeResolver attributeResolver = component.getComponent();
- am = new SAML2AttributesMapper(attributeResolver);
- captiveServiceReloadFailed = false;
- lastReload = when;
- }
- } finally {
- if (null != component) {
- component.unpinComponent();
- }
- }
-
- try {
- if (null != am) {
- am.initialize();
- }
- } catch (final ComponentInitializationException e) {
- log.error("Error initializing AttributeMapper", e);
- }
-
- attributesMapper = am;
- return am;
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/ScopedStringAttributeValueMapper.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/ScopedStringAttributeValueMapper.java
deleted file mode 100644
index a356831..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/ScopedStringAttributeValueMapper.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeValueMapper;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.opensaml.core.xml.XMLObject;
-
-import com.google.common.base.Objects;
-
-/**
- * Mapping to extract a {@link net.shibboleth.idp.attribute.ScopedStringAttributeValue} from an AttributeValue.
- */
-public class ScopedStringAttributeValueMapper extends AbstractSAMLAttributeValueMapper {
-
- /** The scope delimiter. */
- private String delimiter = "@";
-
- /**
- * Returns the delimiter.
- *
- * @return the delimiter
- */
- @Nonnull public String getDelimiter() {
- return delimiter;
- }
-
- /**
- * Sets the delimiter.
- *
- * @param delim what to set.
- */
- public void setDelimiter(@Nonnull @NotEmpty final String delim) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- final String trimmed = StringSupport.trimOrNull(delim);
- Constraint.isNotNull(trimmed, "ScopedStringAttributeDecoder: delimiter can not be empty null");
- delimiter = trimmed;
- }
-
- /** {@inheritDoc} */
- @Nullable protected IdPAttributeValue<?> decodeValue(@Nonnull final XMLObject object) {
- Constraint.isNotNull(object, "Object supplied to must not be null");
- final String stringValue = getStringValue(object);
-
- if (null == stringValue) {
- return null;
- }
-
- final int offset = stringValue.indexOf(getDelimiter());
-
- if (offset < 0) {
- return null;
- }
-
- return ScopedStringAttributeValue.valueOf(stringValue.substring(0, offset), stringValue.substring(offset
- + getDelimiter().length()));
- }
-
- /** {@inheritDoc} */
- @Nonnull protected String getAttributeTypeName() {
- return "Scoped";
- }
-
- /** {@inheritDoc} */
- public boolean equals(final Object obj) {
- if (obj == null) {
- return false;
- }
-
- if (obj == this) {
- return true;
- }
-
- if (obj instanceof ScopedStringAttributeValueMapper) {
- final ScopedStringAttributeValueMapper other = (ScopedStringAttributeValueMapper) obj;
- return java.util.Objects.equals(getDelimiter(), other.getDelimiter());
- }
- return false;
- }
-
- /** {@inheritDoc} */
- public int hashCode() {
- return Objects.hashCode(getAttributeTypeName(), getDelimiter());
- }
-
-}
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/StringAttributeValueMapper.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/StringAttributeValueMapper.java
deleted file mode 100644
index aca6bbd..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/StringAttributeValueMapper.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeValueMapper;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-
-import org.opensaml.core.xml.XMLObject;
-
-/**
- * Mapping extract a {@link org.opensaml.core.xml.schema.XSString} from an {@link IdPAttributeValue}.
- */
-public class StringAttributeValueMapper extends AbstractSAMLAttributeValueMapper {
-
- /** {@inheritDoc} */
- @Nullable protected IdPAttributeValue<?> decodeValue(final XMLObject object) {
- Constraint.isNotNull(object, "Object supplied to must not be null");
- final String value = getStringValue(object);
- if (null == value) {
- return null;
- }
- return StringAttributeValue.valueOf(value);
- }
-
- /** {@inheritDoc} */
- @Nonnull protected String getAttributeTypeName() {
- return "String";
- }
-}
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/XMLObjectAttributeValueMapper.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/XMLObjectAttributeValueMapper.java
deleted file mode 100644
index 3d59d39..0000000
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/mapping/impl/XMLObjectAttributeValueMapper.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeValueMapper;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-
-import org.opensaml.core.xml.XMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-
-/**
- * Decoder for {@link XMLObject} into {@link XMLObjectAttributeValue}.
- */
-public class XMLObjectAttributeValueMapper extends AbstractSAMLAttributeValueMapper {
-
- /** logger . */
- private Logger log = LoggerFactory.getLogger(XMLObjectAttributeValueMapper.class);
-
- /** Do we treat the entire AttributeValue as the object to be embedded. */
- private boolean includeAttributeValue;
-
- /** Do we include the attribute value, or just its first child?
- * @return Returns the includeAttributeValue.
- */
- public boolean isIncludeAttributeValue() {
- return includeAttributeValue;
- }
-
- /** Sets whether we look at the AttributeValue, or just its child.
- * @param doInclude The includeAttributeValue to set.
- */
- public void setIncludeAttributeValue(final boolean doInclude) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- includeAttributeValue = doInclude;
- }
-
-
- /** {@inheritDoc} */
- @Nullable protected IdPAttributeValue decodeValue(@Nonnull final XMLObject object) {
- Constraint.isNotNull(object, "Object supplied to must not be null");
-
- if (includeAttributeValue) {
- return new XMLObjectAttributeValue(object);
- }
-
- final List<XMLObject> children = object.getOrderedChildren();
-
- if (null == children || children.isEmpty()) {
- log.debug("{} attribute had no XML children, ignored", getLogPrefix());
- return null;
- }
- if (children.size() > 1) {
- log.debug("{} attribute has more than one child, returning first value only", getLogPrefix());
- }
- final XMLObject child = children.get(0);
- log.debug("{} returning value of type {}", getLogPrefix(), child.getClass().toString());
- return new XMLObjectAttributeValue(child);
- }
-
- /** {@inheritDoc} */
- @Nonnull protected String getAttributeTypeName() {
- return "XMLObject";
- }
-
- /** {@inheritDoc} */
- public boolean equals(final Object obj) {
- if (obj == null) {
- return false;
- }
-
- if (obj == this) {
- return true;
- }
-
- if (obj instanceof XMLObjectAttributeValueMapper) {
- final XMLObjectAttributeValueMapper other = (XMLObjectAttributeValueMapper) obj;
- return isIncludeAttributeValue() == other.isIncludeAttributeValue();
- }
- return false;
- }
-
- /** {@inheritDoc} */
- public int hashCode() {
- return Objects.hashCode(getClass(), isIncludeAttributeValue());
- }
-}
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoder.java
new file mode 100644
index 0000000..02f500c
--- /dev/null
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoder.java
@@ -0,0 +1,84 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.ByteAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
+import net.shibboleth.utilities.java.support.codec.Base64Support;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
+import org.opensaml.saml.saml1.core.AttributeValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link net.shibboleth.idp.attribute.AttributeTranscoder} that supports {@link Attribute} and
+ * {@link ByteAttributeValue} objects.
+ */
+public class SAML1ByteAttributeTranscoder extends AbstractSAML1AttributeTranscoder<ByteAttributeValue> {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1ByteAttributeTranscoder.class);
+
+ /** {@inheritDoc} */
+ @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
+ @Nonnull final IdPAttributeValue value) {
+ return value instanceof ByteAttributeValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
+ @Nonnull final ByteAttributeValue value) throws AttributeEncodingException {
+
+ final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
+
+ return SAMLEncoderSupport.encodeByteArrayValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
+ encodeType);
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected IdPAttributeValue<?> decodeValue(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
+ @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
+
+ final String s = getStringValue(value);
+ if (null == s) {
+ return null;
+ }
+
+ final byte[] decoded = Base64Support.decode(s);
+ if (decoded.length == 0) {
+ log.warn("Ignoring non-base64-encoded value");
+ return null;
+ }
+
+ return ByteAttributeValue.valueOf(decoded);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoder.java
new file mode 100644
index 0000000..4ddefdc
--- /dev/null
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoder.java
@@ -0,0 +1,134 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.namespace.QName;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+
+import org.opensaml.core.xml.AttributeExtensibleXMLObject;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
+import org.opensaml.saml.saml1.core.AttributeValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link net.shibboleth.idp.attribute.AttributeTranscoder} that supports {@link AttributeDesignator} and
+ * {@link ScopedStringAttributeValue} objects.
+ */
+public class SAML1ScopedStringAttributeTranscoder extends AbstractSAML1AttributeTranscoder<ScopedStringAttributeValue> {
+
+ /** One of "inline" or "attribute", controlling the style of XML encoding. */
+ @Nonnull @NotEmpty public static final String PROP_SCOPE_TYPE = "scopeType";
+
+ /** Name of XML attribute when scopeType property is "attribute". */
+ @Nonnull @NotEmpty public static final String PROP_SCOPE_ATTR_NAME = "scopeAttributeName";
+
+ /** Scope delimiter when scopeType property is "inline". */
+ @Nonnull @NotEmpty public static final String PROP_SCOPE_DELIMITER = "scopeDelimiter";
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1ScopedStringAttributeTranscoder.class);
+
+ /** {@inheritDoc} */
+ @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
+ @Nonnull final IdPAttributeValue value) {
+ return value instanceof ScopedStringAttributeValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
+ @Nonnull final ScopedStringAttributeValue value) throws AttributeEncodingException {
+
+ final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
+
+ final String scopeType = rule.getOrDefault(PROP_SCOPE_TYPE, String.class, "attribute");
+
+ if ("attribute".equals(scopeType)) {
+ final String scopeAttributeName = rule.getOrDefault(PROP_SCOPE_ATTR_NAME, String.class, "Scope");
+ return SAMLEncoderSupport.encodeScopedStringValueAttribute(attribute,
+ AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeAttributeName, encodeType);
+ } else if ("inline".equals(scopeType)) {
+ final String scopeDelimiter = rule.getOrDefault(PROP_SCOPE_DELIMITER, String.class, "@");
+ return SAMLEncoderSupport.encodeScopedStringValueInline(
+ attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeDelimiter, encodeType);
+ } else {
+ throw new AttributeEncodingException("Invalid scopeType property (must be inline or attribute)");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected IdPAttributeValue<?> decodeValue(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
+ @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
+
+ if (value == null) {
+ return null;
+ }
+
+ final String stringValue = getStringValue(value);
+ if (null == stringValue) {
+ return null;
+ }
+
+ final String scopeType = rule.getOrDefault(PROP_SCOPE_TYPE, String.class, "attribute");
+ if ("attribute".equals(scopeType)) {
+ if (value instanceof AttributeExtensibleXMLObject) {
+ final String scopeValue = ((AttributeExtensibleXMLObject) value).getUnknownAttributes().get(
+ new QName(rule.getOrDefault(PROP_SCOPE_ATTR_NAME, String.class, "Scope")));
+
+ if (scopeValue == null) {
+ log.warn("Scope not found in designated XML attribute");
+ return null;
+ }
+
+ return ScopedStringAttributeValue.valueOf(stringValue, scopeValue);
+ } else {
+ log.warn("Object does not support required interface to access the scope via XML attribute");
+ return null;
+ }
+ } else if ("inline".equals(scopeType)) {
+ final String scopeDelimiter = rule.getOrDefault(PROP_SCOPE_DELIMITER, String.class, "@");
+ final int offset = stringValue.indexOf(scopeDelimiter);
+ if (offset < 0) {
+ log.warn("Ignoring value with no scope delimiter ({})", scopeDelimiter);
+ return null;
+ }
+
+ return ScopedStringAttributeValue.valueOf(stringValue.substring(0, offset), stringValue.substring(offset
+ + scopeDelimiter.length()));
+
+ } else {
+ log.error("Invalid scopeType property (must be inline or attribute)");
+ return null;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1StringAttributeEncoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoder.java
similarity index 52%
rename from idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1StringAttributeEncoder.java
rename to idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoder.java
index 7b80268..3e595ad 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1StringAttributeEncoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoder.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package net.shibboleth.idp.saml.attribute.encoding.impl;
+package net.shibboleth.idp.saml.attribute.transcoding.impl;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -26,38 +26,54 @@ import net.shibboleth.idp.attribute.IdPAttributeValue;
import net.shibboleth.idp.attribute.LocalizedStringAttributeValue;
import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.idp.saml.attribute.encoding.AbstractSAML1AttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.SAMLEncoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
import org.opensaml.core.xml.XMLObject;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
import org.opensaml.saml.saml1.core.AttributeValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * {@link net.shibboleth.idp.attribute.AttributeEncoder} that produces SAML 1 attributes from an
- * {@link net.shibboleth.idp.attribute.IdPAttribute} that contains <code>String</code> values.
+ * {@link net.shibboleth.idp.attribute.AttributeTranscoder} that supports {@link AttributeDesignator} and
+ * {@link StringAttributeValue} objects.
*/
-public class SAML1StringAttributeEncoder extends AbstractSAML1AttributeEncoder<StringAttributeValue> {
+public class SAML1StringAttributeTranscoder extends AbstractSAML1AttributeTranscoder<StringAttributeValue> {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1StringAttributeEncoder.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1StringAttributeTranscoder.class);
/** {@inheritDoc} */
- @Override
- protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute, @Nonnull final IdPAttributeValue value) {
+ @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
+ @Nonnull final IdPAttributeValue value) {
return value instanceof StringAttributeValue;
}
/** {@inheritDoc} */
- @Override
- @Nullable protected XMLObject encodeValue(@Nonnull final IdPAttribute attribute,
+ @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
@Nonnull final StringAttributeValue value) throws AttributeEncodingException {
+
if (value instanceof LocalizedStringAttributeValue || value instanceof ScopedStringAttributeValue) {
log.warn("Attribute '{}': Lossy encoding of attribute value of type {} to SAML1 String Attribute",
- attribute.getId(), value.getClass().getName());
+ attribute.getId(), value.getClass().getSimpleName());
}
- return SAMLEncoderSupport.encodeStringValue(attribute,
- AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(), encodeType());
+
+ final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
+
+ return SAMLEncoderSupport.encodeStringValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
+ encodeType);
}
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected IdPAttributeValue<?> decodeValue(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
+ @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
+
+ return value != null ? StringAttributeValue.valueOf(getStringValue(value)) : null;
+ }
+
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1XMLObjectAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1XMLObjectAttributeTranscoder.java
new file mode 100644
index 0000000..761ce51
--- /dev/null
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1XMLObjectAttributeTranscoder.java
@@ -0,0 +1,97 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
+import org.opensaml.saml.saml1.core.AttributeValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link net.shibboleth.idp.attribute.AttributeTranscoder} that supports {@link AttributeDesignator} and
+ * {@link XMLObjectAttributeValue} objects.
+ */
+public class SAML1XMLObjectAttributeTranscoder extends AbstractSAML1AttributeTranscoder<XMLObjectAttributeValue> {
+
+ /** Property indicating whether to decode the AttributeValue element itself, or its child element. */
+ @Nonnull @NotEmpty public static final String PROP_INCLUDE_ATTR_VALUE = "includeAttributeValue";
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SAML1XMLObjectAttributeTranscoder.class);
+
+ /** {@inheritDoc} */
+ @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
+ @Nonnull final IdPAttributeValue value) {
+ return value instanceof XMLObjectAttributeValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
+ @Nonnull final XMLObjectAttributeValue value) throws AttributeEncodingException {
+
+ return SAMLEncoderSupport.encodeXMLObjectValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME,
+ value.getValue());
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected IdPAttributeValue<?> decodeValue(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
+ @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
+
+ if (value == null) {
+ return null;
+ }
+
+ final Boolean includeAttributeValue = rule.getOrDefault(PROP_INCLUDE_ATTR_VALUE, Boolean.class, Boolean.FALSE);
+ if (includeAttributeValue) {
+ return new XMLObjectAttributeValue(value);
+ }
+
+ final List<XMLObject> children = value.getOrderedChildren();
+
+ if (null == children || children.isEmpty()) {
+ log.debug("Ignoring XMLObject with no child elements");
+ return null;
+ }
+ if (children.size() > 1) {
+ log.debug("XMLObject has more than one child, returning first element only");
+ }
+
+ final XMLObject child = children.get(0);
+ log.debug("Returning value of type {}", child.getClass().getSimpleName());
+ return new XMLObjectAttributeValue(child);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoder.java
new file mode 100644
index 0000000..b58a3d4
--- /dev/null
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoder.java
@@ -0,0 +1,84 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.ByteAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
+import net.shibboleth.utilities.java.support.codec.Base64Support;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link net.shibboleth.idp.attribute.AttributeTranscoder} that supports {@link Attribute} and
+ * {@link ByteAttributeValue} objects.
+ */
+public class SAML2ByteAttributeTranscoder extends AbstractSAML2AttributeTranscoder<ByteAttributeValue> {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SAML2ByteAttributeTranscoder.class);
+
+ /** {@inheritDoc} */
+ @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
+ @Nonnull final IdPAttributeValue value) {
+ return value instanceof ByteAttributeValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
+ @Nonnull final ByteAttributeValue value) throws AttributeEncodingException {
+
+ final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
+
+ return SAMLEncoderSupport.encodeByteArrayValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
+ encodeType);
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected IdPAttributeValue<?> decodeValue(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
+ @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
+
+ final String s = getStringValue(value);
+ if (null == s) {
+ return null;
+ }
+
+ final byte[] decoded = Base64Support.decode(s);
+ if (decoded.length == 0) {
+ log.warn("Ignoring non-base64-encoded value");
+ return null;
+ }
+
+ return ByteAttributeValue.valueOf(decoded);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoder.java
new file mode 100644
index 0000000..5dbdf9b
--- /dev/null
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoder.java
@@ -0,0 +1,135 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.namespace.QName;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+
+import org.opensaml.core.xml.AttributeExtensibleXMLObject;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link net.shibboleth.idp.attribute.AttributeTranscoder} that supports {@link Attribute} and
+ * {@link ScopedStringAttributeValue} objects.
+ */
+public class SAML2ScopedStringAttributeTranscoder extends AbstractSAML2AttributeTranscoder<ScopedStringAttributeValue> {
+
+ /** One of "inline" or "attribute", controlling the style of XML encoding. */
+ @Nonnull @NotEmpty public static final String PROP_SCOPE_TYPE = "scopeType";
+
+ /** Name of XML attribute when scopeType property is "attribute". */
+ @Nonnull @NotEmpty public static final String PROP_SCOPE_ATTR_NAME = "scopeAttributeName";
+
+ /** Scope delimiter when scopeType property is "inline". */
+ @Nonnull @NotEmpty public static final String PROP_SCOPE_DELIMITER = "scopeDelimiter";
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SAML2ScopedStringAttributeTranscoder.class);
+
+ /** {@inheritDoc} */
+ @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
+ @Nonnull final IdPAttributeValue value) {
+ return value instanceof ScopedStringAttributeValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
+ @Nonnull final ScopedStringAttributeValue value) throws AttributeEncodingException {
+
+ final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
+
+ final String scopeType = rule.getOrDefault(PROP_SCOPE_TYPE, String.class, "inline");
+
+ if ("attribute".equals(scopeType)) {
+ final String scopeAttributeName = rule.getOrDefault(PROP_SCOPE_ATTR_NAME, String.class, "Scope");
+ return SAMLEncoderSupport.encodeScopedStringValueAttribute(attribute,
+ AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeAttributeName, encodeType);
+ } else if ("inline".equals(scopeType)) {
+ final String scopeDelimiter = rule.getOrDefault(PROP_SCOPE_DELIMITER, String.class, "@");
+ return SAMLEncoderSupport.encodeScopedStringValueInline(
+ attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeDelimiter, encodeType);
+ } else {
+ throw new AttributeEncodingException("Invalid scopeType property (must be inline or attribute)");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected IdPAttributeValue<?> decodeValue(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
+ @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
+
+ if (value == null) {
+ return null;
+ }
+
+ final String stringValue = getStringValue(value);
+ if (null == stringValue) {
+ return null;
+ }
+
+ final String scopeType = rule.getOrDefault(PROP_SCOPE_TYPE, String.class, "inline");
+ if ("attribute".equals(scopeType)) {
+
+ if (value instanceof AttributeExtensibleXMLObject) {
+ final String scopeValue = ((AttributeExtensibleXMLObject) value).getUnknownAttributes().get(
+ new QName(null, rule.getOrDefault(PROP_SCOPE_ATTR_NAME, String.class, "Scope")));
+ if (scopeValue == null) {
+ log.warn("Scope not found in designated XML attribute");
+ return null;
+ }
+
+ return ScopedStringAttributeValue.valueOf(stringValue, scopeValue);
+
+ } else {
+ log.warn("Object does not support required interface to access the scope via XML attribute");
+ return null;
+ }
+ } else if ("inline".equals(scopeType)) {
+ final String scopeDelimiter = rule.getOrDefault(PROP_SCOPE_DELIMITER, String.class, "@");
+ final int offset = stringValue.indexOf(scopeDelimiter);
+ if (offset < 0) {
+ log.warn("Ignoring value with no scope delimiter ({})", scopeDelimiter);
+ return null;
+ }
+
+ return ScopedStringAttributeValue.valueOf(stringValue.substring(0, offset), stringValue.substring(offset
+ + scopeDelimiter.length()));
+
+ } else {
+ log.error("Invalid scopeType property (must be inline or attribute)");
+ return null;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2StringAttributeEncoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoder.java
similarity index 56%
rename from idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2StringAttributeEncoder.java
rename to idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoder.java
index d317a93..64d95b8 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2StringAttributeEncoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoder.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package net.shibboleth.idp.saml.attribute.encoding.impl;
+package net.shibboleth.idp.saml.attribute.transcoding.impl;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -23,31 +23,28 @@ import javax.annotation.Nullable;
import net.shibboleth.idp.attribute.AttributeEncodingException;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.IdPRequestedAttribute;
import net.shibboleth.idp.attribute.LocalizedStringAttributeValue;
import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.idp.saml.attribute.encoding.AbstractSAML2AttributeEncoder;
-import net.shibboleth.idp.saml.attribute.encoding.AttributeMapperProcessor;
-import net.shibboleth.idp.saml.attribute.encoding.SAMLEncoderSupport;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.StringAttributeValueMapper;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
import org.opensaml.core.xml.XMLObject;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml2.core.Attribute;
import org.opensaml.saml.saml2.core.AttributeValue;
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * {@link net.shibboleth.idp.attribute.AttributeEncoder} that produces a SAML 2 Attribute from an {@link IdPAttribute}
- * that contains <code>String</code> values.
+ * {@link net.shibboleth.idp.attribute.AttributeTranscoder} that supports {@link Attribute} and
+ * {@link StringAttributeValue} objects.
*/
-public class SAML2StringAttributeEncoder extends AbstractSAML2AttributeEncoder<StringAttributeValue> implements
- AttributeMapperProcessor<RequestedAttribute, IdPRequestedAttribute> {
+public class SAML2StringAttributeTranscoder extends AbstractSAML2AttributeTranscoder<StringAttributeValue> {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(SAML2StringAttributeEncoder.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SAML2StringAttributeTranscoder.class);
/** {@inheritDoc} */
@Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
@@ -56,22 +53,27 @@ public class SAML2StringAttributeEncoder extends AbstractSAML2AttributeEncoder<S
}
/** {@inheritDoc} */
- @Override @Nullable protected XMLObject encodeValue(@Nonnull final IdPAttribute attribute,
+ @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
@Nonnull final StringAttributeValue value) throws AttributeEncodingException {
+
if (value instanceof LocalizedStringAttributeValue || value instanceof ScopedStringAttributeValue) {
log.warn("Attribute '{}': Lossy encoding of attribute value of type {} to SAML2 String Attribute",
- attribute.getId(), value.getClass().getName());
+ attribute.getId(), value.getClass().getSimpleName());
}
- return SAMLEncoderSupport.encodeStringValue(attribute,
- AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(), encodeType());
+
+ final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
+
+ return SAMLEncoderSupport.encodeStringValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
+ encodeType);
}
/** {@inheritDoc} */
- @Override @Nonnull public void populateAttributeMapper(
- final AbstractSAMLAttributeMapper<RequestedAttribute, IdPRequestedAttribute> mapper) {
- mapper.setAttributeFormat(getNameFormat());
- mapper.setId(getMapperId());
- mapper.setSAMLName(getName());
- mapper.setValueMapper(new StringAttributeValueMapper());
+ @Override @Nullable protected IdPAttributeValue<?> decodeValue(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
+ @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
+
+ return value != null ? StringAttributeValue.valueOf(getStringValue(value)) : null;
}
+
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoder.java
new file mode 100644
index 0000000..6d9ee65
--- /dev/null
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoder.java
@@ -0,0 +1,97 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link net.shibboleth.idp.attribute.AttributeTranscoder} that supports {@link Attribute} and
+ * {@link XMLObjectAttributeValue} objects.
+ */
+public class SAML2XMLObjectAttributeTranscoder extends AbstractSAML2AttributeTranscoder<XMLObjectAttributeValue> {
+
+ /** Property indicating whether to decode the AttributeValue element itself, or its child element. */
+ @Nonnull @NotEmpty public static final String PROP_INCLUDE_ATTR_VALUE = "includeAttributeValue";
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SAML2XMLObjectAttributeTranscoder.class);
+
+ /** {@inheritDoc} */
+ @Override protected boolean canEncodeValue(@Nonnull final IdPAttribute attribute,
+ @Nonnull final IdPAttributeValue value) {
+ return value instanceof XMLObjectAttributeValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
+ @Nonnull final XMLObjectAttributeValue value) throws AttributeEncodingException {
+
+ return SAMLEncoderSupport.encodeXMLObjectValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME,
+ value.getValue());
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable protected IdPAttributeValue<?> decodeValue(
+ @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
+ @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
+
+ if (value == null) {
+ return null;
+ }
+
+ final Boolean includeAttributeValue = rule.getOrDefault(PROP_INCLUDE_ATTR_VALUE, Boolean.class, Boolean.FALSE);
+ if (includeAttributeValue) {
+ return new XMLObjectAttributeValue(value);
+ }
+
+ final List<XMLObject> children = value.getOrderedChildren();
+
+ if (null == children || children.isEmpty()) {
+ log.debug("Ignoring XMLObject with no child elements");
+ return null;
+ }
+ if (children.size() > 1) {
+ log.debug("XMLObject has more than one child, returning first element only");
+ }
+
+ final XMLObject child = children.get(0);
+ log.debug("Returning value of type {}", child.getClass().getSimpleName());
+ return new XMLObjectAttributeValue(child);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/package-info.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/package-info.java
similarity index 85%
rename from idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/package-info.java
rename to idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/package-info.java
index 3760d3e..d7ff608 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/encoding/impl/package-info.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/package-info.java
@@ -15,6 +15,8 @@
* limitations under the License.
*/
-/** SAML specific {@link net.shibboleth.idp.attribute.AttributeEncoder} implementations. */
+/**
+ * Implementations of SAML transcoders.
+ */
-package net.shibboleth.idp.saml.attribute.encoding.impl;
\ No newline at end of file
+package net.shibboleth.idp.saml.attribute.transcoding.impl;
\ 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..e2e8c72 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 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.attribute.transcoding.TranscodingRule;
+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<TranscodingRule> rulesets = registry.getTranscodingRules(input);
+
+ for (final TranscodingRule 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/profile/impl/BaseAddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
index e48e2b6..bcadefb 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
@@ -17,12 +17,19 @@
package net.shibboleth.idp.saml.profile.impl;
+import java.util.Collection;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.context.AttributeContext;
+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.attribute.transcoding.TranscodingRule;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.idp.profile.config.navigate.IdentifierGenerationStrategyLookupFunction;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
@@ -31,12 +38,17 @@ import net.shibboleth.idp.profile.context.navigate.ResponderIdLookupFunction;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.common.SAMLObject;
+import net.shibboleth.utilities.java.support.annotation.constraint.Live;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
import net.shibboleth.utilities.java.support.security.IdentifierGenerationStrategy;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.slf4j.Logger;
@@ -49,11 +61,13 @@ import org.slf4j.LoggerFactory;
* an {@link AttributeContext} returned from a
* lookup strategy, by default located on the {@link RelyingPartyContext} beneath the profile request context.</p>
*
+ * @param <T> type of objects being encoded
+ *
* @event {@link EventIds#PROCEED_EVENT_ID}
* @event {@link EventIds#INVALID_MSG_CTX}
* @event {@link EventIds#INVALID_PROFILE_CTX}
*/
-public abstract class BaseAddAttributeStatementToAssertion extends AbstractProfileAction {
+public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject> extends AbstractProfileAction {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(BaseAddAttributeStatementToAssertion.class);
@@ -79,6 +93,9 @@ public abstract class BaseAddAttributeStatementToAssertion extends AbstractProfi
*/
@Nonnull private Function<ProfileRequestContext,AttributeContext> attributeContextLookupStrategy;
+ /** Transcoder registry service object. */
+ @NonnullAfterInit private ReloadableService<AttributeTranscoderRegistry> transcoderRegistry;
+
/** AttributeContext to use. */
@Nullable private AttributeContext attributeCtx;
@@ -187,6 +204,26 @@ public abstract class BaseAddAttributeStatementToAssertion extends AbstractProfi
issuerLookupStrategy = Constraint.isNotNull(strategy, "Issuer lookup strategy cannot be null");
}
+
+ /**
+ * Gets the registry of transcoding rules to apply to encode attributes.
+ *
+ * @return registry
+ */
+ @NonnullAfterInit public ReloadableService<AttributeTranscoderRegistry> getTranscoderRegistry() {
+ return transcoderRegistry;
+ }
+
+ /**
+ * Sets the registry of transcoding rules to apply to encode attributes.
+ *
+ * @param registry registry service interface
+ */
+ public void setTranscoderRegistry(@Nonnull final ReloadableService<AttributeTranscoderRegistry> registry) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ transcoderRegistry = Constraint.isNotNull(registry, "AttributeTranscoderRegistry cannot be null");
+ }
/**
* Get the {@link AttributeContext} to encode.
@@ -220,6 +257,16 @@ public abstract class BaseAddAttributeStatementToAssertion extends AbstractProfi
/** {@inheritDoc} */
@Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (transcoderRegistry == null) {
+ throw new ComponentInitializationException("AttributeTranscoderRegistry cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
if (!super.doPreExecute(profileRequestContext)) {
return false;
@@ -250,4 +297,52 @@ public abstract class BaseAddAttributeStatementToAssertion extends AbstractProfi
return true;
}
+
+ /**
+ * Access the registry of transcoding rules to transform the input attribute into a target type.
+ *
+ * @param registry registry of transcoding rules
+ * @param profileRequestContext current profile request context
+ * @param attribute input attribute
+ * @param to target type
+ * @param results collection to add results to
+ *
+ * @return number of results added
+ *
+ * @throws AttributeEncodingException if a non-ignorable error occurs
+ */
+ protected int encodeAttribute(@Nonnull final AttributeTranscoderRegistry registry,
+ @Nonnull final ProfileRequestContext profileRequestContext, @Nonnull final IdPAttribute attribute,
+ @Nonnull final Class<T> to, @Nonnull @NonnullElements @Live final Collection<T> results)
+ throws AttributeEncodingException {
+
+ final Collection<TranscodingRule> transcodingRules = registry.getTranscodingRules(attribute, to);
+ if (transcodingRules.isEmpty()) {
+ log.debug("{} Attribute {} does not have any transcoding rules, nothing to do", getLogPrefix(),
+ attribute.getId());
+ return 0;
+ }
+
+ int count = 0;
+
+ for (final TranscodingRule rules : transcodingRules) {
+ try {
+ final AttributeTranscoder<T> transcoder = TranscoderSupport.<T>getTranscoder(rules);
+ final T encodedAttribute = transcoder.encode(profileRequestContext, attribute, to, rules);
+ if (encodedAttribute != null) {
+ results.add(encodedAttribute);
+ count++;
+ }
+ } catch (final AttributeEncodingException e) {
+ if (isIgnoringUnencodableAttributes()) {
+ log.debug("{} Unable to encode attribute {}", getLogPrefix(), attribute.getId(), e);
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ return count;
+ }
+
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java
index b3ccd54..9a94785 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java
@@ -19,29 +19,27 @@ package net.shibboleth.idp.saml.saml1.profile.impl;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.AttributeEncodingException;
import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
import net.shibboleth.idp.profile.IdPEventIds;
-import net.shibboleth.idp.saml.attribute.encoding.SAML1AttributeEncoder;
import net.shibboleth.idp.saml.profile.impl.BaseAddAttributeStatementToAssertion;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NullableElements;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.saml.common.SAMLObjectBuilder;
-import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml1.core.Assertion;
import org.opensaml.saml.saml1.core.Attribute;
import org.opensaml.saml.saml1.core.AttributeStatement;
@@ -68,7 +66,7 @@ import com.google.common.collect.Collections2;
* @event {@link EventIds#INVALID_MSG_CTX}
* @event {@link IdPEventIds#UNABLE_ENCODE_ATTRIBUTE}
*/
-public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementToAssertion {
+public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementToAssertion<Attribute> {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddAttributeStatementToAssertion.class);
@@ -137,8 +135,20 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
}
final ArrayList<Attribute> encodedAttributes = new ArrayList<>(attributes.size());
- for (final IdPAttribute attribute : Collections2.filter(attributes, Predicates.notNull())) {
- encodeAttribute(profileRequestContext, attribute, encodedAttributes);
+
+ ServiceableComponent<AttributeTranscoderRegistry> component = null;
+ try {
+ component = getTranscoderRegistry().getServiceableComponent();
+ if (component == null) {
+ throw new AttributeEncodingException("Attribute transoding service unavailable");
+ }
+ for (final IdPAttribute attribute : Collections2.filter(attributes, Predicates.notNull())) {
+ encodeAttribute(component.getComponent(), profileRequestContext, attribute, encodedAttributes);
+ }
+ } finally {
+ if (null != component) {
+ component.unpinComponent();
+ }
}
if (encodedAttributes.isEmpty()) {
@@ -156,50 +166,25 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
}
/**
- * Encodes a {@link IdPAttribute} into zero or more {@link Attribute} objects if a proper encoder is available.
+ * Encodes {@link IdPAttribute} into zero or more {@link Attribute} objects if a proper encoder is available.
*
+ * @param registry transcoding registry
* @param profileRequestContext current profile request context
* @param attribute the attribute to be encoded
* @param results collection to add the encoded SAML attributes to
*
* @throws AttributeEncodingException thrown if there is a problem encoding an attribute
*/
- private void encodeAttribute(@Nonnull final ProfileRequestContext profileRequestContext,
+ private void encodeAttribute(@Nonnull final AttributeTranscoderRegistry registry,
+ @Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final IdPAttribute attribute, @Nonnull @NonnullElements final Collection<Attribute> results)
throws AttributeEncodingException {
log.debug("{} Attempting to encode attribute {} as a SAML 1 Attribute", getLogPrefix(), attribute.getId());
-
- final Set<AttributeEncoder<?>> encoders = attribute.getEncoders();
- if (encoders.isEmpty()) {
- log.debug("{} Attribute {} does not have any encoders, nothing to do", getLogPrefix(), attribute.getId());
- return;
- }
-
- boolean added = false;
-
- for (final AttributeEncoder<?> encoder : encoders) {
- if (SAMLConstants.SAML11P_NS.equals(encoder.getProtocol())
- && encoder instanceof SAML1AttributeEncoder
- && encoder.getActivationCondition().test(profileRequestContext)) {
- log.debug("{} Encoding attribute {} as a SAML 1 Attribute", getLogPrefix(), attribute.getId());
- try {
- added = true;
- results.add((Attribute) encoder.encode(attribute));
- } catch (final AttributeEncodingException e) {
- if (isIgnoringUnencodableAttributes()) {
- log.debug("{} Unable to encode attribute {} as SAML 1 attribute", getLogPrefix(),
- attribute.getId(), e);
- } else {
- throw e;
- }
- }
- }
- }
- if (!added) {
- log.debug(
- "{} Attribute {} did not have a usable SAML 1 Attribute encoder associated with it, nothing to do",
+ // Uses the new registry.
+ if (super.encodeAttribute(registry, profileRequestContext, attribute, Attribute.class, results) == 0) {
+ log.debug("{} Attribute {} did not have SAML 1 Attribute transcoder instructions associated, nothing to do",
getLogPrefix(), attribute.getId());
}
}
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java
index d6bba98..b773978 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java
@@ -19,6 +19,8 @@ package net.shibboleth.idp.saml.saml1.profile.impl;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nonnull;
@@ -26,6 +28,8 @@ import javax.annotation.Nullable;
import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.messaging.context.navigate.MessageLookup;
+import org.opensaml.profile.action.ActionSupport;
+import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
import org.opensaml.saml.saml1.core.AttributeDesignator;
@@ -34,15 +38,23 @@ import org.opensaml.saml.saml1.core.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.Multimap;
-
+import net.shibboleth.idp.attribute.AttributeDecodingException;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.context.AttributeContext;
+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.attribute.transcoding.TranscodingRule;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapper;
+import net.shibboleth.utilities.java.support.annotation.constraint.Live;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
/**
* Action that filters a set of attributes against the {@link org.opensaml.saml.saml1.core.AttributeDesignator}
@@ -55,9 +67,9 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(FilterByQueriedAttributeDesignators.class);
- /** Mapper used to get the engine used to filter attributes. */
- @Nonnull private final AttributesMapper<AttributeDesignator,IdPAttribute> map;
-
+ /** Transcoder registry service object. */
+ @NonnullAfterInit private ReloadableService<AttributeTranscoderRegistry> transcoderRegistry;
+
/** Strategy used to locate the {@link Request} containing the query to filter against. */
@Nonnull private Function<ProfileRequestContext,Request> requestLookupStrategy;
@@ -70,15 +82,8 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
/** AttributeContext to filter. */
@Nullable private AttributeContext attributeContext;
- /**
- * Constructor.
- *
- * @param mapper mapper used to consume designators
- */
- public FilterByQueriedAttributeDesignators(@Nonnull final
- AttributesMapper<AttributeDesignator,IdPAttribute> mapper) {
- map = Constraint.isNotNull(mapper, "Mapper cannot be null");
-
+ /** Constructor. */
+ public FilterByQueriedAttributeDesignators() {
attributeContextLookupStrategy = new ChildContextLookup<>(AttributeContext.class).compose(
new ChildContextLookup<>(RelyingPartyContext.class));
@@ -86,6 +91,17 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
}
/**
+ * Sets the registry of transcoding rules to apply to encode attributes.
+ *
+ * @param registry registry service interface
+ */
+ public void setTranscoderRegistry(@Nonnull final ReloadableService<AttributeTranscoderRegistry> registry) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ transcoderRegistry = Constraint.isNotNull(registry, "AttributeTranscoderRegistry cannot be null");
+ }
+
+ /**
* Set the strategy used to locate the {@link Request} associated with a given {@link ProfileRequestContext}.
*
* @param strategy lookup strategy
@@ -112,6 +128,16 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
/** {@inheritDoc} */
@Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (transcoderRegistry == null) {
+ throw new ComponentInitializationException("AttributeTranscoderRegistry cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
if (!super.doPreExecute(profileRequestContext)) {
@@ -146,13 +172,37 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
- final Collection<IdPAttribute> keepers = new ArrayList<>(query.getAttributeDesignators().size());
+ final Set<String> decodedAttributeIds = new HashSet<>();
+
+ ServiceableComponent<AttributeTranscoderRegistry> component = null;
+ try {
+ component = transcoderRegistry.getServiceableComponent();
+ if (component == null) {
+ log.error("Attribute transcoder service unavailable");
+ ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_PROC_ERROR);
+ return;
+ }
+
+ for (final AttributeDesignator designator : query.getAttributeDesignators()) {
+ try {
+ decodeAttributeDesignator(component.getComponent(), profileRequestContext, designator,
+ decodedAttributeIds);
+ } catch (final AttributeDecodingException e) {
+ log.warn("{} Error decoding AttributeDesignators", getLogPrefix(), e);
+ }
+ }
+ } finally {
+ if (component != null) {
+ component.unpinComponent();
+ }
+ }
+
- final Multimap<String,IdPAttribute> mapped = map.mapAttributes(query.getAttributeDesignators());
- log.debug("Query content mapped to attribute IDs: {}", mapped.keySet());
+ final Collection<IdPAttribute> keepers = new ArrayList<>(query.getAttributeDesignators().size());
+ log.debug("Query content mapped to attribute IDs: {}", decodedAttributeIds);
for (final IdPAttribute attribute : attributeContext.getIdPAttributes().values()) {
- if (mapped.containsKey(attribute.getId())) {
+ if (decodedAttributeIds.contains(attribute.getId())) {
log.debug("Retaining attribute '{}' requested by query", attribute.getId());
keepers.add(attribute);
} else {
@@ -163,4 +213,34 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
attributeContext.setIdPAttributes(keepers);
}
+ /**
+ * Access the registry of transcoding rules to decode the input {@link AttributeDesignator}.
+ *
+ * @param registry registry of transcoding rules
+ * @param profileRequestContext current profile request context
+ * @param input input object
+ * @param results collection to add attributeIDs to
+ *
+ * @throws AttributeDecodingException if an error occurs or no results were obtained
+ */
+ private void decodeAttributeDesignator(@Nonnull final AttributeTranscoderRegistry registry,
+ @Nonnull final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator input,
+ @Nonnull @NonnullElements @Live final Collection<String> results)
+ throws AttributeDecodingException {
+
+ final Collection<TranscodingRule> transcodingRules = registry.getTranscodingRules(input);
+ if (transcodingRules.isEmpty()) {
+ throw new AttributeDecodingException("No transcoding rule for AttributeDesignator '" +
+ input.getAttributeName() + "'");
+ }
+
+ for (final TranscodingRule rules : transcodingRules) {
+ final AttributeTranscoder<AttributeDesignator> transcoder = TranscoderSupport.getTranscoder(rules);
+ final IdPAttribute decodedAttribute = transcoder.decode(profileRequestContext, input, rules);
+ if (decodedAttribute != null) {
+ results.add(decodedAttribute.getId());
+ }
+ }
+ }
+
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java
index 56f03b2..d3e2f04 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java
@@ -19,29 +19,27 @@ package net.shibboleth.idp.saml.saml2.profile.impl;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import net.shibboleth.idp.attribute.AttributeEncoder;
import net.shibboleth.idp.attribute.AttributeEncodingException;
import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
import net.shibboleth.idp.profile.IdPEventIds;
-import net.shibboleth.idp.saml.attribute.encoding.SAML2AttributeEncoder;
import net.shibboleth.idp.saml.profile.impl.BaseAddAttributeStatementToAssertion;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NullableElements;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.saml.common.SAMLObjectBuilder;
-import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.Attribute;
import org.opensaml.saml.saml2.core.AttributeStatement;
@@ -69,7 +67,7 @@ import com.google.common.collect.Collections2;
* @event {@link EventIds#INVALID_MSG_CTX}
* @event {@link IdPEventIds#UNABLE_ENCODE_ATTRIBUTE}
*/
-public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementToAssertion {
+public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementToAssertion<Attribute> {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddAttributeStatementToAssertion.class);
@@ -139,8 +137,20 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
}
final ArrayList<Attribute> encodedAttributes = new ArrayList<>(attributes.size());
- for (final IdPAttribute attribute : Collections2.filter(attributes, Predicates.notNull())) {
- encodeAttribute(profileRequestContext, attribute, encodedAttributes);
+
+ ServiceableComponent<AttributeTranscoderRegistry> component = null;
+ try {
+ component = getTranscoderRegistry().getServiceableComponent();
+ if (component == null) {
+ throw new AttributeEncodingException("Attribute transoding service unavailable");
+ }
+ for (final IdPAttribute attribute : Collections2.filter(attributes, Predicates.notNull())) {
+ encodeAttribute(component.getComponent(), profileRequestContext, attribute, encodedAttributes);
+ }
+ } finally {
+ if (null != component) {
+ component.unpinComponent();
+ }
}
if (encodedAttributes.isEmpty()) {
@@ -160,48 +170,23 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
/**
* Encodes a {@link IdPAttribute} into zero or more {@link Attribute} objects if a proper encoder is available.
*
+ * @param registry transcoding registry
* @param profileRequestContext current profile request context
* @param attribute the attribute to be encoded
* @param results collection to add the encoded SAML attributes to
*
* @throws AttributeEncodingException thrown if there is a problem encoding an attribute
*/
- private void encodeAttribute(@Nonnull final ProfileRequestContext profileRequestContext,
+ private void encodeAttribute(@Nonnull final AttributeTranscoderRegistry registry,
+ @Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final IdPAttribute attribute, @Nonnull @NonnullElements final Collection<Attribute> results)
throws AttributeEncodingException {
log.debug("{} Attempting to encode attribute {} as a SAML 2 Attribute", getLogPrefix(), attribute.getId());
-
- final Set<AttributeEncoder<?>> encoders = attribute.getEncoders();
- if (encoders.isEmpty()) {
- log.debug("{} Attribute {} does not have any encoders, nothing to do", getLogPrefix(), attribute.getId());
- return;
- }
-
- boolean added = false;
-
- for (final AttributeEncoder<?> encoder : encoders) {
- if (SAMLConstants.SAML20P_NS.equals(encoder.getProtocol())
- && encoder instanceof SAML2AttributeEncoder
- && encoder.getActivationCondition().test(profileRequestContext)) {
- log.debug("{} Encoding attribute {} as a SAML 2 Attribute", getLogPrefix(), attribute.getId());
- try {
- results.add((Attribute) encoder.encode(attribute));
- added = true;
- } catch (final AttributeEncodingException e) {
- if (isIgnoringUnencodableAttributes()) {
- log.debug("{} Unable to encode attribute {} as SAML 2 attribute", getLogPrefix(),
- attribute.getId(), e);
- } else {
- throw e;
- }
- }
- }
- }
- if (!added) {
- log.debug(
- "{} Attribute {} did not have a usable SAML 2 Attribute encoder associated with it, nothing to do",
+ // Uses the new registry.
+ if (super.encodeAttribute(registry, profileRequestContext, attribute, Attribute.class, results) == 0) {
+ log.debug("{} Attribute {} did not have SAML 2 Attribute transcoder instructions associated, nothing to do",
getLogPrefix(), attribute.getId());
}
}
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java
index f2c303f..2c75274 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java
@@ -26,6 +26,8 @@ import javax.annotation.Nullable;
import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.messaging.context.navigate.MessageLookup;
+import org.opensaml.profile.action.ActionSupport;
+import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
import org.opensaml.saml.saml2.core.Attribute;
@@ -33,17 +35,27 @@ import org.opensaml.saml.saml2.core.AttributeQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
+import net.shibboleth.idp.attribute.AttributeDecodingException;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.IdPAttributeValue;
import net.shibboleth.idp.attribute.context.AttributeContext;
+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.attribute.transcoding.TranscodingRule;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapper;
+import net.shibboleth.utilities.java.support.annotation.constraint.Live;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
/**
* Action that filters a set of attributes against the {@link org.opensaml.saml.saml2.core.Attribute} objects in
@@ -56,8 +68,8 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(FilterByQueriedAttributes.class);
- /** Service used to get the engine used to filter attributes. */
- @Nonnull private final AttributesMapper<Attribute, IdPAttribute> mapper;
+ /** Transcoder registry service object. */
+ @NonnullAfterInit private ReloadableService<AttributeTranscoderRegistry> transcoderRegistry;
/** Strategy used to locate the {@link AttributeQuery} to filter against. */
@Nonnull private Function<ProfileRequestContext,AttributeQuery> queryLookupStrategy;
@@ -71,14 +83,8 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
/** AttributeContext to filter. */
@Nullable private AttributeContext attributeContext;
- /**
- * Constructor.
- *
- * @param theMapper mapper used to consume designators
- */
- public FilterByQueriedAttributes(@Nonnull final AttributesMapper<Attribute, IdPAttribute> theMapper) {
- mapper = Constraint.isNotNull(theMapper, "Mapper cannot be null");
-
+ /** Constructor. */
+ public FilterByQueriedAttributes() {
attributeContextLookupStrategy = new ChildContextLookup<>(AttributeContext.class).compose(
new ChildContextLookup<>(RelyingPartyContext.class));
@@ -86,6 +92,17 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
}
/**
+ * Sets the registry of transcoding rules to apply to encode attributes.
+ *
+ * @param registry registry service interface
+ */
+ public void setTranscoderRegistry(@Nonnull final ReloadableService<AttributeTranscoderRegistry> registry) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ transcoderRegistry = Constraint.isNotNull(registry, "AttributeTranscoderRegistry cannot be null");
+ }
+
+ /**
* Set the strategy used to locate the {@link AttributeQuery} associated with a given {@link ProfileRequestContext}.
*
* @param strategy lookup strategy
@@ -112,6 +129,16 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
/** {@inheritDoc} */
@Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (transcoderRegistry == null) {
+ throw new ComponentInitializationException("AttributeTranscoderRegistry cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
if (!super.doPreExecute(profileRequestContext)) {
@@ -142,11 +169,34 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
/** {@inheritDoc} */
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
-
- final Collection<IdPAttribute> keepers = new ArrayList<>(query.getAttributes().size());
-
- final Multimap<String,IdPAttribute> mapped = mapper.mapAttributes(query.getAttributes());
+
+ final Multimap<String,IdPAttribute> mapped = HashMultimap.create();
+
+ ServiceableComponent<AttributeTranscoderRegistry> component = null;
+ try {
+ component = transcoderRegistry.getServiceableComponent();
+ if (component == null) {
+ log.error("Attribute transcoder service unavailable");
+ ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_PROC_ERROR);
+ return;
+ }
+
+ for (final Attribute designator : query.getAttributes()) {
+ try {
+ decodeAttribute(component.getComponent(), profileRequestContext, designator, mapped);
+ } catch (final AttributeDecodingException e) {
+ log.error("{} Error decoding queried Attribute", getLogPrefix(), e);
+ }
+ }
+ } finally {
+ if (component != null) {
+ component.unpinComponent();
+ }
+ }
+
log.debug("{} Query content mapped to attribute IDs: {}", getLogPrefix(), mapped.keySet());
+
+ final Collection<IdPAttribute> keepers = new ArrayList<>(query.getAttributes().size());
for (final IdPAttribute attribute : attributeContext.getIdPAttributes().values()) {
@@ -174,6 +224,35 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
}
/**
+ * Access the registry of transcoding rules to decode the input {@link Attribute}.
+ *
+ * @param registry registry of transcoding rules
+ * @param profileRequestContext current profile request context
+ * @param input input object
+ * @param results collection to add results to
+ *
+ * @throws AttributeDecodingException if an error occurs or no results were obtained
+ */
+ protected void decodeAttribute(@Nonnull final AttributeTranscoderRegistry registry,
+ @Nonnull final ProfileRequestContext profileRequestContext, @Nonnull final Attribute input,
+ @Nonnull @NonnullElements @Live final Multimap<String,IdPAttribute> results)
+ throws AttributeDecodingException {
+
+ final Collection<TranscodingRule> transcodingRules = registry.getTranscodingRules(input);
+ if (transcodingRules.isEmpty()) {
+ throw new AttributeDecodingException("No transcoding rule for Attribute '" + input.getName() + "'");
+ }
+
+ for (final TranscodingRule rules : transcodingRules) {
+ final AttributeTranscoder<Attribute> transcoder = TranscoderSupport.getTranscoder(rules);
+ final IdPAttribute decodedAttribute = transcoder.decode(profileRequestContext, input, rules);
+ if (decodedAttribute != null) {
+ results.put(decodedAttribute.getId(), decodedAttribute);
+ }
+ }
+ }
+
+ /**
* Adjust an input attribute's values based on any values requested.
*
* @param attribute attribute to filter
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);
}
}
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ByteAttributeEncoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ByteAttributeEncoderTest.java
deleted file mode 100644
index ecaa61b..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ByteAttributeEncoderTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.schema.XSBase64Binary;
-import org.opensaml.saml.saml1.core.Attribute;
-import org.opensaml.saml.saml1.core.AttributeValue;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.utilities.java.support.codec.Base64Support;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-/**
- * {@link SAML1ByteAttributeEncoder} Unit test.
- *
- * Identical code to the {@link SAML1ByteAttributeEncoder} except that the type of assertion and encoder is changed.
- */
-public class SAML1ByteAttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- /** The name we give the test attribute. */
- private final static String ATTR_NAME = "foo";
-
- /** A test value. */
- private final static byte[] BYTE_ARRAY_1 = {1, 2, 3, 4, 5};
-
- /** A second test value. */
- private final static byte[] BYTE_ARRAY_2 = {4, 3, 2, 1};
-
- private SAML1ByteAttributeEncoder encoder;
-
- @BeforeClass public void initTest() throws ComponentInitializationException {
- encoder = new SAML1ByteAttributeEncoder();
- encoder.setName(ATTR_NAME);
- encoder.setNamespace("NameSpace");
- encoder.setEncodeType(true);
- encoder.initialize();
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void empty() throws Exception {
- final IdPAttribute inputAttribute;
-
- inputAttribute = new IdPAttribute(ATTR_NAME);
-
- encoder.encode(inputAttribute);
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
- final int[] intArray = {1, 2, 3, 4};
- final List<IdPAttributeValue<?>> values =
- Arrays.asList(new StringAttributeValue("foo"), new ScopedStringAttributeValue(
- "foo", "bar"), new IdPAttributeValue<Object>() {
- public Object getValue() {
- return intArray;
- }
-
- public String getDisplayValue() {
- return intArray.toString();
- }
- });
-
- IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- encoder.encode(inputAttribute);
- }
-
- @Test public void single() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(new StringAttributeValue("foo"), new ByteAttributeValue(BYTE_ARRAY_1));
- final IdPAttribute inputAttribute;
-
- inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- List<XMLObject> children = outputAttribute.getOrderedChildren();
-
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
-
- XMLObject child = children.get(0);
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME);
-
- Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
-
- XSBase64Binary childAsString = (XSBase64Binary) child;
-
- byte childAsBa[] = Base64Support.decode(childAsString.getValue());
-
- Assert.assertEquals(childAsBa, BYTE_ARRAY_1, "Input equals output");
- }
-
- @Test public void multi() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(new ByteAttributeValue(BYTE_ARRAY_1),
- new ByteAttributeValue(BYTE_ARRAY_2));
-
- final IdPAttribute inputAttribute;
- inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 2, "Encoding two entries");
-
- XMLObject child = children.get(0);
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
-
- XSBase64Binary childAsString = (XSBase64Binary) child;
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- final byte[] res0 = Base64Support.decode(childAsString.getValue());
-
- child = children.get(1);
- Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
-
- childAsString = (XSBase64Binary) child;
- final byte[] res1 = Base64Support.decode(childAsString.getValue());
-
- //
- // order of results is not guaranteed so sense the result from the length
- //
- if (BYTE_ARRAY_1.length == res0.length) {
- Assert.assertEquals(BYTE_ARRAY_1, res0, "Input matches output");
- Assert.assertEquals(BYTE_ARRAY_2, res1, "Input matches output");
- } else if (BYTE_ARRAY_1.length == res1.length) {
- Assert.assertEquals(BYTE_ARRAY_1, res1, "Input matches output");
- Assert.assertEquals(BYTE_ARRAY_2, res0, "Input matches output");
- } else {
- Assert.assertTrue(BYTE_ARRAY_1.length == res1.length || BYTE_ARRAY_2.length == res1.length,
- "One of the output's size should match an input size");
- }
- }
-
-}
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ScopedStringAttributeEncoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ScopedStringAttributeEncoderTest.java
deleted file mode 100644
index c1d725e..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1ScopedStringAttributeEncoderTest.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml1.core.Attribute;
-import org.opensaml.saml.saml1.core.AttributeValue;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.idp.saml.xmlobject.ScopedValue;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.UninitializedComponentException;
-
-/**
- * {@link SAML1ScopedStringAttributeEncoder} Unit test.
- */
-public class SAML1ScopedStringAttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- /** The name we give the test attribute. */
- private final static String ATTR_NAME = "foo";
-
- /** A test value. */
- private final static String VALUE_1 = "ValueTheFirst";
-
- /** A second test value. */
- private final static String VALUE_2 = "Second";
-
- /** A test scope . */
- private final static String SCOPE_1 = "scope1.example.org";
-
- /** A second test value. */
- private final static String SCOPE_2 = "scope2";
-
- private final static String DELIMITER = "#";
-
- private final static String ATTRIBUTE_NAME = "Scope";
-
- private final ScopedStringAttributeValue value1 = new ScopedStringAttributeValue(VALUE_1, SCOPE_1);
-
- private final ScopedStringAttributeValue value2 = new ScopedStringAttributeValue(VALUE_2, SCOPE_2);
-
- public SAML1ScopedStringAttributeEncoder makeEncoder() {
- final SAML1ScopedStringAttributeEncoder encoder = new SAML1ScopedStringAttributeEncoder();
- encoder.setName(ATTR_NAME);
- encoder.setScopeAttributeName(ATTRIBUTE_NAME);
- encoder.setNamespace("NameSpace");
- encoder.setEncodeType(true);
- return encoder;
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void empty()
- throws AttributeEncodingException, ComponentInitializationException {
- final IdPAttribute inputAttribute;
-
- inputAttribute = new IdPAttribute(ATTR_NAME);
-
- SAML1ScopedStringAttributeEncoder encoder = makeEncoder();
- encoder.initialize();
- encoder.encode(inputAttribute);
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate()
- throws AttributeEncodingException, ComponentInitializationException {
- final SAML1ScopedStringAttributeEncoder encoder = makeEncoder();
- final int[] intArray = {1, 2, 3, 4};
- final List<IdPAttributeValue<?>> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue("dd"),
- new IdPAttributeValue<Object>() {
- @Override
- public Object getValue() {
- return intArray;
- }
- public String getDisplayValue() {
- return intArray.toString();
- }
- });
-
- final IdPAttribute inputAttribute;
- inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
- try {
- encoder.encode(inputAttribute);
- Assert.fail("not initialized");
- } catch (UninitializedComponentException e) {
- // OK
- }
- encoder.initialize();
-
- encoder.encode(inputAttribute);
- }
-
- @Test public void single() throws ComponentInitializationException, AttributeEncodingException {
- final SAML1ScopedStringAttributeEncoder encoder = makeEncoder();
- try {
- encoder.setScopeAttributeName(null);
- encoder.initialize();
- Assert.fail("Missing attribute name should throw");
- } catch (ComponentInitializationException e) {
- // OK
- }
- encoder.setScopeAttributeName(ATTRIBUTE_NAME);
- encoder.setScopeDelimiter(DELIMITER);
-
- final List<IdPAttributeValue<?>> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), value1);
-
- final IdPAttribute inputAttribute;
- inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- encoder.initialize();
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
-
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
-
- final XMLObject child = children.get(0);
-
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- Assert.assertTrue(child instanceof ScopedValue, "Child of result attribute should be a string");
-
- final ScopedValue childAsScopedValue = (ScopedValue) child;
-
- Assert.assertEquals(childAsScopedValue.getValue(), VALUE_1, "Input equals output");
- Assert.assertEquals(childAsScopedValue.getScope(), SCOPE_1, "Input equals output");
-
- }
-
- @Test public void multi() throws ComponentInitializationException, AttributeEncodingException {
- final SAML1ScopedStringAttributeEncoder encoder = makeEncoder();
- encoder.initialize();
- final List<IdPAttributeValue<?>> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), value1, value2);
-
- final IdPAttribute inputAttribute;
- inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 2, "Encoding two entries");
-
- Assert.assertTrue(children.get(0) instanceof ScopedValue && children.get(1) instanceof ScopedValue,
- "Child of result attribute should be a string");
-
- final ScopedValue child1 = (ScopedValue) children.get(0);
- Assert.assertEquals(child1.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- final ScopedValue child2 = (ScopedValue) children.get(1);
- Assert.assertEquals(child2.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- //
- // order of results is not guaranteed so sense the result from the length
- //
- if (child1.getValue().length() == VALUE_1.length()) {
- Assert.assertEquals(child1.getValue(), VALUE_1, "Input matches output");
- Assert.assertEquals(child2.getValue(), VALUE_2, "Input matches output");
- Assert.assertEquals(child1.getScope(), SCOPE_1, "Input matches output");
- Assert.assertEquals(child2.getScope(), SCOPE_2, "Input matches output");
- } else if (child1.getValue().length() == VALUE_2.length()) {
- Assert.assertEquals(child2.getValue(), VALUE_1, "Input matches output");
- Assert.assertEquals(child1.getValue(), VALUE_2, "Input matches output");
- Assert.assertEquals(child2.getScope(), SCOPE_1, "Input matches output");
- Assert.assertEquals(child1.getScope(), SCOPE_2, "Input matches output");
- } else {
- Assert.fail("Value mismatch");
- }
- }
-
- @Test public void singleInline() throws ComponentInitializationException, AttributeEncodingException {
- final SAML1ScopedStringAttributeEncoder encoder = makeEncoder();
- encoder.setScopeType("wibble");
- try {
- encoder.initialize();
- Assert.fail("Bad type should throw");
- } catch (ComponentInitializationException e) {
- // OK
- }
-
- encoder.setScopeType("inline");
- encoder.setScopeDelimiter(DELIMITER);
- encoder.initialize();
-
- final List<IdPAttributeValue<?>> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), value1);
-
- final IdPAttribute inputAttribute;
- inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
-
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
-
- final XMLObject child = children.get(0);
-
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
-
- final XSString childAsString = (XSString) child;
-
- Assert.assertEquals(childAsString.getValue(), VALUE_1 + DELIMITER + SCOPE_1, "Input equals output");
- }
-
- @Test public void multiInline() throws Exception {
- final SAML1ScopedStringAttributeEncoder encoder = makeEncoder();
- encoder.setScopeType("inline");
- encoder.setScopeDelimiter(DELIMITER);
- encoder.setScopeAttributeName(null);
- encoder.initialize();
- final List<IdPAttributeValue<?>> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), value1, value2);
-
- final IdPAttribute inputAttribute;
- inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 2, "Encoding two entries");
-
- Assert.assertTrue(children.get(0) instanceof XSString && children.get(1) instanceof XSString,
- "Child of result attribute should be a string");
-
- final XSString child1 = (XSString) children.get(0);
- Assert.assertEquals(child1.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- final XSString child2 = (XSString) children.get(1);
- Assert.assertEquals(child2.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- //
- // order of results is not guaranteed so sense the result from the length
- //
- if (child1.getValue().equals(VALUE_1 + DELIMITER + SCOPE_1)) {
- Assert.assertEquals(child2.getValue(), VALUE_2 + DELIMITER + SCOPE_2, "Input matches output");
- } else {
- Assert.assertEquals(child1.getValue(), VALUE_2 + DELIMITER + SCOPE_2, "Input matches output");
- Assert.assertEquals(child2.getValue(), VALUE_1 + DELIMITER + SCOPE_1, "Input matches output");
- }
- }
-
-}
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1StringAttributeEncoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1StringAttributeEncoderTest.java
deleted file mode 100644
index 9e6b68c..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1StringAttributeEncoderTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml1.core.Attribute;
-import org.opensaml.saml.saml1.core.AttributeValue;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-/**
- * {@link SAML1StringAttributeEncoder} Unit test.
- */
-public class SAML1StringAttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- /** The name we give the test attribute. */
- private final static String ATTR_NAME = "foo";
-
- /** A test value. */
- private final static String STRING_1 = "Value The First";
-
- /** A second test value. */
- private final static String STRING_2 = "Second string the value is";
-
- private SAML1StringAttributeEncoder encoder;
-
- @BeforeClass public void initTest() throws ComponentInitializationException {
- encoder = new SAML1StringAttributeEncoder();
- encoder.setName(ATTR_NAME);
- encoder.setNamespace("NameSpace");
- encoder.setEncodeType(true);
- encoder.initialize();
- }
-
- @Test(expectedExceptions={AttributeEncodingException.class,}) public void empty() throws Exception {
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
-
- encoder.encode(inputAttribute);
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
- encoder.initialize();
- final int[] intArray = {1, 2, 3, 4};
- final List<IdPAttributeValue<?>> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
- new IdPAttributeValue<Object>() {
- @Override
- public Object getValue() {
- return intArray;
- }
- @Override
- public String getDisplayValue() {
- return intArray.toString();
- }
- });
-
- final IdPAttribute inputAttribute;
- inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- encoder.encode(inputAttribute);
- }
-
- @Test public void single() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
-
- final IdPAttribute inputAttribute;
- inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
-
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
-
- final XMLObject child = children.get(0);
-
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
-
- final XSString childAsString = (XSString) child;
-
- Assert.assertEquals(childAsString.getValue(), STRING_1, "Input equals output");
- }
-
- @Test public void multi() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}),
- new StringAttributeValue(STRING_1),
- new StringAttributeValue(STRING_2),
- new ScopedStringAttributeValue(STRING_2, STRING_1));
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 3, "Encoding three entries");
-
- for (final XMLObject child: children) {
- Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
- final String childAsString = ((XSString) children.get(0)).getValue();
- Assert.assertTrue(STRING_1.equals(childAsString)||STRING_2.equals(childAsString));
- }
- }
-
-}
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1XMLObjectAttributeEncoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1XMLObjectAttributeEncoderTest.java
deleted file mode 100644
index c27c41a..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML1XMLObjectAttributeEncoderTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml1.core.Attribute;
-import org.opensaml.saml.saml1.core.AttributeValue;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-/**
- * {@link SAML1XMLObjectAttributeEncoder} Unit test.
- *
- * Identical code to the {@link SAML1ByteAttributeEncoder} except that the type of assertion and encoder is changed.
- */
-public class SAML1XMLObjectAttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- /** The name we give the test attribute. */
- private final static String ATTR_NAME = "foo";
-
- /** A test value. */
- private final static String STRING_1 = "Value The First";
-
- /** A second test value. */
- private final static String STRING_2 = "Second string the value is";
-
- private SAML1XMLObjectAttributeEncoder encoder;
-
- private SAML1StringAttributeEncoder strEncoder;
-
- @BeforeClass public void initTest() throws ComponentInitializationException {
- encoder = new SAML1XMLObjectAttributeEncoder();
- encoder.setName(ATTR_NAME);
- encoder.setNamespace("NameSpace");
- encoder.initialize();
- strEncoder = new SAML1StringAttributeEncoder();
- strEncoder.setName(ATTR_NAME);
- strEncoder.setNamespace("NameSpace");
- strEncoder.setEncodeType(true);
- strEncoder.initialize();
- }
-
- /**
- * Create an XML object from a string which we can test against later. We use the Saml1StringEncoder to do the work
- * because it is handy in this package.
- *
- * @param value that we encode
- * @return an XML object
- */
- private XMLObjectAttributeValue ObjectFor(final String value) {
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(Collections.singletonList(new StringAttributeValue(value)));
- try {
- return new XMLObjectAttributeValue(strEncoder.encode(inputAttribute));
- } catch (AttributeEncodingException e) {
- return null;
- }
- }
-
- /**
- * Check that the input XML object is what was expected.
- *
- * @param input the objects in question.
- * @param possibles the strings that they might be encoding.
- */
- private static void CheckValues(final XMLObject input, final String... possibles) {
- Assert.assertTrue(input instanceof Attribute);
- final Attribute attribute = (Attribute) input;
-
- final List<XMLObject> children = attribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 1, "Data must have but one entry");
- Assert.assertTrue(children.get(0) instanceof XSString, "Data must contain one string");
- final String s = ((XSString) children.get(0)).getValue();
-
- for (String possible : possibles) {
- if (s.equals(possible)) {
- return;
- }
- }
- Assert.assertTrue(false, "No potential match");
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void empty() throws Exception {
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
-
- encoder.encode(inputAttribute);
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
- final int[] intArray = {1, 2, 3, 4};
- final List<IdPAttributeValue<?>> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
- new ScopedStringAttributeValue("foo", "bar"), new IdPAttributeValue<Object>() {
- @Override
- public Object getValue() {
- return intArray;
- }
- public String getDisplayValue() {
- return intArray.toString();
- }
- });
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- encoder.encode(inputAttribute);
- }
-
- @Test public void single() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), ObjectFor(STRING_1));
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
- Assert.assertEquals(children.get(0).getElementQName(),
- AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- Assert.assertEquals(children.get(0).getOrderedChildren().size(), 1,
- "Expected exactly one child inside the <AttributeValue/>");
-
- CheckValues(children.get(0).getOrderedChildren().get(0), STRING_1);
- }
-
- @Test public void testMulti() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(ObjectFor(STRING_1), ObjectFor(STRING_2));
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 2, "Encoding two entries");
-
- Assert.assertEquals(children.get(0).getElementQName(),
- AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- Assert.assertEquals(children.get(0).getOrderedChildren().size(), 1,
- "Expected exactly one child inside the <AttributeValue/> for first Attribute");
-
- Assert.assertEquals(children.get(1).getElementQName(),
- AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- Assert.assertEquals(children.get(1).getOrderedChildren().size(), 1,
- "Expected exactly one child inside the <AttributeValue/> for second Attribute");
-
- CheckValues(children.get(0).getOrderedChildren().get(0), STRING_1, STRING_2);
- CheckValues(children.get(1).getOrderedChildren().get(0), STRING_1, STRING_2);
- }
-}
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ByteAttributeEncoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ByteAttributeEncoderTest.java
deleted file mode 100644
index 35dd30b..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ByteAttributeEncoderTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.schema.XSBase64Binary;
-import org.opensaml.saml.saml2.core.Attribute;
-import org.opensaml.saml.saml2.core.AttributeValue;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.utilities.java.support.codec.Base64Support;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-/**
- * {@link SAML2ByteAttributeEncoder} Unit test.
- *
- * Identical code to the {@link SAML1ByteAttributeEncoder} except that the type of assertion and encoder is changed.
- */
-public class SAML2ByteAttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- /** The name we give the test attribute. */
- private final static String ATTR_NAME = "foo";
-
- /** A test value. */
- private final static byte[] BYTE_ARRAY_1 = {1, 2, 3, 4, 5};
-
- /** A second test value. */
- private final static byte[] BYTE_ARRAY_2 = {4, 3, 2, 1};
-
- private SAML2ByteAttributeEncoder encoder;
-
- @BeforeClass public void initTest() throws ComponentInitializationException {
- encoder = new SAML2ByteAttributeEncoder();
- encoder.setName(ATTR_NAME);
- encoder.setNameFormat("NameSpace");
- encoder.setFriendlyName("friendly");
- encoder.setEncodeType(true);
- encoder.initialize();
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void empty() throws Exception {
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
-
- encoder.encode(inputAttribute);
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
- final int[] intArray = {1, 2, 3, 4};
- final List<IdPAttributeValue<?>> values =
- Arrays.asList(new StringAttributeValue("foo"), new ScopedStringAttributeValue("foo", "bar"),
- new IdPAttributeValue<Object>() {
- public Object getValue() {
- return intArray;
- }
- public String getDisplayValue() {
- return intArray.toString();
- }
- });
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- encoder.encode(inputAttribute);
- }
-
- @Test public void single() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(new StringAttributeValue("foo"), new ByteAttributeValue(BYTE_ARRAY_1));
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- List<XMLObject> children = outputAttribute.getOrderedChildren();
-
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
-
- XMLObject child = children.get(0);
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME);
-
- Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
-
- XSBase64Binary childAsString = (XSBase64Binary) child;
-
- byte childAsBa[] = Base64Support.decode(childAsString.getValue());
-
- Assert.assertEquals(childAsBa, BYTE_ARRAY_1, "Input equals output");
- }
-
- @Test public void multi() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(new ByteAttributeValue(BYTE_ARRAY_1), new ByteAttributeValue(BYTE_ARRAY_2));
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 2, "Encoding two entries");
-
- XMLObject child = children.get(0);
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
-
- XSBase64Binary childAsString = (XSBase64Binary) child;
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- final byte[] res0 = Base64Support.decode(childAsString.getValue());
-
- child = children.get(1);
- Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
-
- childAsString = (XSBase64Binary) child;
- final byte[] res1 = Base64Support.decode(childAsString.getValue());
-
- //
- // order of results is not guaranteed so sense the result from the length
- //
- if (BYTE_ARRAY_1.length == res0.length) {
- Assert.assertEquals(BYTE_ARRAY_1, res0, "Input matches output");
- Assert.assertEquals(BYTE_ARRAY_2, res1, "Input matches output");
- } else if (BYTE_ARRAY_1.length == res1.length) {
- Assert.assertEquals(BYTE_ARRAY_1, res1, "Input matches output");
- Assert.assertEquals(BYTE_ARRAY_2, res0, "Input matches output");
- } else {
- Assert.assertTrue(BYTE_ARRAY_1.length == res1.length || BYTE_ARRAY_2.length == res1.length,
- "One of the output's size should match an input size");
- }
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ScopedStringAttributeEncoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ScopedStringAttributeEncoderTest.java
deleted file mode 100644
index d3d6ce9..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2ScopedStringAttributeEncoderTest.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml2.core.Attribute;
-import org.opensaml.saml.saml2.core.AttributeValue;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.idp.saml.xmlobject.ScopedValue;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.UninitializedComponentException;
-
-/**
- * {@link SAML2ScopedStringAttributeEncoder} Unit test. Looks a lot like the SAML1 one
- */
-public class SAML2ScopedStringAttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- /** The name we give the test attribute. */
- private final static String ATTR_NAME = "foo";
-
- /** A test value. */
- private final static String VALUE_1 = "ValueTheFirst";
-
- /** A second test value. */
- private final static String VALUE_2 = "Second";
-
- /** A test scope . */
- private final static String SCOPE_1 = "scope1.example.org";
-
- /** A second test value. */
- private final static String SCOPE_2 = "scope2";
-
- private final static String DELIMITER = "#";
-
- private final static String ATTRIBUTE_NAME = "Scope";
-
- private final ScopedStringAttributeValue value1 = new ScopedStringAttributeValue(VALUE_1, SCOPE_1);
-
- private final ScopedStringAttributeValue value2 = new ScopedStringAttributeValue(VALUE_2, SCOPE_2);
-
- public SAML2ScopedStringAttributeEncoder makeEncoder() {
- SAML2ScopedStringAttributeEncoder encoder;
- encoder = new SAML2ScopedStringAttributeEncoder();
- encoder.setName(ATTR_NAME);
- encoder.setScopeDelimiter(DELIMITER);
- encoder.setNameFormat("NameSpace");
- encoder.setFriendlyName("friendly");
- encoder.setEncodeType(true);
- return encoder;
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void empty()
- throws AttributeEncodingException, ComponentInitializationException {
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
-
- SAML2ScopedStringAttributeEncoder encoder = makeEncoder();
- encoder.initialize();
-
- encoder.encode(inputAttribute);
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate()
- throws AttributeEncodingException, ComponentInitializationException {
- final SAML2ScopedStringAttributeEncoder encoder = makeEncoder();
- final int[] intArray = {1, 2, 3, 4};
- final var values =
- List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue("dd"),
- new IdPAttributeValue<Object>() {
- public Object getValue() {
- return intArray;
- }
- public String getDisplayValue() {
- return intArray.toString();
- }
- });
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
- try {
- encoder.encode(inputAttribute);
- Assert.fail("not initialized");
- } catch (UninitializedComponentException e) {
- // OK
- }
- encoder.initialize();
-
- encoder.encode(inputAttribute);
- }
-
- @Test public void singleAttribute() throws ComponentInitializationException, AttributeEncodingException {
- final SAML2ScopedStringAttributeEncoder encoder = makeEncoder();
- encoder.setScopeType("attribute");
- try {
- encoder.setScopeAttributeName(null);
- encoder.initialize();
- Assert.fail("Missing attribute name should throw");
- } catch (ComponentInitializationException e) {
- // OK
- }
- encoder.setScopeAttributeName(ATTRIBUTE_NAME);
- encoder.setScopeDelimiter(DELIMITER);
-
- final Collection<IdPAttributeValue<?>> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), value1);
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- encoder.initialize();
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
-
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
-
- final XMLObject child = children.get(0);
-
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- Assert.assertTrue(child instanceof ScopedValue, "Child of result attribute should be a string");
-
- final ScopedValue childAsScopedValue = (ScopedValue) child;
-
- Assert.assertEquals(childAsScopedValue.getValue(), VALUE_1, "Input equals output");
- Assert.assertEquals(childAsScopedValue.getScope(), SCOPE_1, "Input equals output");
-
- }
-
- @Test public void multiAttribute() throws ComponentInitializationException, AttributeEncodingException {
- final SAML2ScopedStringAttributeEncoder encoder = makeEncoder();
- encoder.setScopeType("attribute");
- encoder.setScopeAttributeName(ATTR_NAME);
- encoder.initialize();
- Collection<IdPAttributeValue<?>> values = List.of(value1, new ByteAttributeValue(new byte[] {1, 2, 3,}), value2);
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 2, "Encoding two entries");
-
- Assert.assertTrue(children.get(0) instanceof ScopedValue && children.get(1) instanceof ScopedValue,
- "Child of result attribute should be a string");
-
- final ScopedValue child1 = (ScopedValue) children.get(0);
- Assert.assertEquals(child1.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- final ScopedValue child2 = (ScopedValue) children.get(1);
- Assert.assertEquals(child2.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- //
- // order of results is not guaranteed so sense the result from the length
- //
- if (child1.getValue().length() == VALUE_1.length()) {
- Assert.assertEquals(child1.getValue(), VALUE_1, "Input matches output");
- Assert.assertEquals(child2.getValue(), VALUE_2, "Input matches output");
- Assert.assertEquals(child1.getScope(), SCOPE_1, "Input matches output");
- Assert.assertEquals(child2.getScope(), SCOPE_2, "Input matches output");
- } else if (child1.getValue().length() == VALUE_2.length()) {
- Assert.assertEquals(child2.getValue(), VALUE_1, "Input matches output");
- Assert.assertEquals(child1.getValue(), VALUE_2, "Input matches output");
- Assert.assertEquals(child2.getScope(), SCOPE_1, "Input matches output");
- Assert.assertEquals(child1.getScope(), SCOPE_2, "Input matches output");
- } else {
- Assert.fail("Value mismatch");
- }
- }
-
- @Test public void singleInline() throws ComponentInitializationException, AttributeEncodingException {
- final SAML2ScopedStringAttributeEncoder encoder = makeEncoder();
- encoder.setScopeType("wibble");
- try {
- encoder.initialize();
- Assert.fail("Bad type should throw");
- } catch (ComponentInitializationException e) {
- // OK
- }
- encoder.setScopeAttributeName(ATTRIBUTE_NAME);
- encoder.setScopeDelimiter("");
- encoder.setScopeType("inline");
- try {
- encoder.initialize();
- Assert.fail("Missing delimiter should throw");
- } catch (ComponentInitializationException e) {
- // OK
- }
- encoder.setScopeDelimiter(DELIMITER);
- encoder.initialize();
-
- final List<IdPAttributeValue<?>> values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), value1);
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
-
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
-
- final XMLObject child = children.get(0);
-
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
-
- final XSString childAsString = (XSString) child;
-
- Assert.assertEquals(childAsString.getValue(), VALUE_1 + DELIMITER + SCOPE_1, "Input equals output");
- }
-
- @Test public void multiInline() throws Exception {
- final SAML2ScopedStringAttributeEncoder encoder = makeEncoder();
- encoder.setScopeDelimiter(DELIMITER);
- encoder.setScopeAttributeName(null);
- encoder.initialize();
- final List<IdPAttributeValue<?>> values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), value1, value2);
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 2, "Encoding two entries");
-
- Assert.assertTrue(children.get(0) instanceof XSString && children.get(1) instanceof XSString,
- "Child of result attribute should be a string");
-
- final XSString child1 = (XSString) children.get(0);
- Assert.assertEquals(child1.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- final XSString child2 = (XSString) children.get(1);
- Assert.assertEquals(child2.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- //
- // order of results is not guaranteed so sense the result from the length
- //
- if (child1.getValue().equals(VALUE_1 + DELIMITER + SCOPE_1)) {
- Assert.assertEquals(child2.getValue(), VALUE_2 + DELIMITER + SCOPE_2, "Input matches output");
- } else {
- Assert.assertEquals(child1.getValue(), VALUE_2 + DELIMITER + SCOPE_2, "Input matches output");
- Assert.assertEquals(child2.getValue(), VALUE_1 + DELIMITER + SCOPE_1, "Input matches output");
- }
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2StringAttributeEncoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2StringAttributeEncoderTest.java
deleted file mode 100644
index 80ce8b6..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2StringAttributeEncoderTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import java.util.List;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml2.core.Attribute;
-import org.opensaml.saml.saml2.core.AttributeValue;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-/**
- * {@link SAML2StringAttributeEncoder} Unit test.
- *
- * Identical code to the {@link SAML1StringAttributeEncoder} except that the type of assertion and encoder is changed.
- */
-public class SAML2StringAttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- /** The name we give the test attribute. */
- private final static String ATTR_NAME = "foo";
-
- /** A test value. */
- private final static String STRING_1 = "Value The First";
-
- /** A second test value. */
- private final static String STRING_2 = "Second string the value is";
-
- private SAML2StringAttributeEncoder encoder;
-
- @BeforeClass public void initTest() throws ComponentInitializationException {
- encoder = new SAML2StringAttributeEncoder();
- encoder.setName(ATTR_NAME);
- encoder.setNameFormat("NameSpace");
- encoder.setFriendlyName("friendly");
- encoder.setEncodeType(true);
- encoder.initialize();
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void empty() throws Exception {
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
-
- encoder.encode(inputAttribute);
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
- final int[] intArray = {1, 2, 3, 4};
- final var values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue<Object>() {
- @Override
- public Object getValue() {
- return intArray;
- }
- @Override
- public String getDisplayValue() {
- return intArray.toString();
- }
- });
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- encoder.encode(inputAttribute);
- }
-
- @Test public void single() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
-
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
-
- final XMLObject child = children.get(0);
-
- Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
-
- Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
-
- final XSString childAsString = (XSString) child;
-
- Assert.assertEquals(childAsString.getValue(), STRING_1, "Input equals output");
- }
-
- @Test public void multi() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}),
- new StringAttributeValue(STRING_1),
- new StringAttributeValue(STRING_2),
- new ScopedStringAttributeValue(STRING_1, STRING_2));
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
-
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 3, "Encoding three entries");
-
- for (final XMLObject child: children) {
- Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
- final String childAsString = ((XSString) children.get(0)).getValue();
- Assert.assertTrue(STRING_1.equals(childAsString)||STRING_2.equals(childAsString));
- }
- }
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2XMLObjectAttributeEncoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2XMLObjectAttributeEncoderTest.java
deleted file mode 100644
index b6675a0..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/encoding/impl/SAML2XMLObjectAttributeEncoderTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * 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.idp.saml.attribute.encoding.impl;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.opensaml.core.OpenSAMLInitBaseTestCase;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.saml2.core.Attribute;
-import org.opensaml.saml.saml2.core.AttributeValue;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import net.shibboleth.idp.attribute.AttributeEncodingException;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttribute;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-/**
- * {@link SAML2XMLObjectAttributeEncoder} Unit test.
- *
- * Identical code to the {@link SAML1XMLObjectAttributeEncoder} except that the type of assertion and encoder is changed.
- */
-public class SAML2XMLObjectAttributeEncoderTest extends OpenSAMLInitBaseTestCase {
-
- /** The name we give the test attribute. */
- private final static String ATTR_NAME = "foo";
-
- /** A test value. */
- private final static String STRING_1 = "Value The First";
-
- /** A second test value. */
- private final static String STRING_2 = "Second string the value is";
-
- private SAML2XMLObjectAttributeEncoder encoder;
-
- private SAML1StringAttributeEncoder strEncoder;
-
- @BeforeClass public void initTest() throws ComponentInitializationException {
- encoder = new SAML2XMLObjectAttributeEncoder();
- encoder.setName(ATTR_NAME);
- encoder.setNameFormat("NameSpace");
- encoder.setFriendlyName("friendly");
- encoder.initialize();
-
- strEncoder = new SAML1StringAttributeEncoder();
- strEncoder.setName(ATTR_NAME);
- strEncoder.setNamespace("NameSpace");
- strEncoder.setEncodeType(true);
- strEncoder.initialize();
- }
-
- /**
- * Create an XML object from a string which we can test against later. We use the Saml1StringEncoder to do the work
- * because it is handy in this package.
- *
- * @param value that we encode
- * @return an XML object
- */
- private XMLObjectAttributeValue ObjectFor(final String value) {
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(Collections.singletonList(new StringAttributeValue(value)));
- try {
- return new XMLObjectAttributeValue(strEncoder.encode(inputAttribute));
- } catch (AttributeEncodingException e) {
- return null;
- }
- }
-
- /**
- * Check that the input XML object is what was expected.
- *
- * @param input the objects in question.
- * @param possibles the strings that they might be encoding.
- */
- private static void CheckValues(final XMLObject input, final String... possibles) {
- Assert.assertTrue(input instanceof org.opensaml.saml.saml1.core.Attribute);
- final org.opensaml.saml.saml1.core.Attribute attribute = (org.opensaml.saml.saml1.core.Attribute) input;
-
- final List<XMLObject> children = attribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 1, "Data must have but one entry");
- Assert.assertTrue(children.get(0) instanceof XSString, "Data must contain one string");
- final String s = ((XSString) children.get(0)).getValue();
-
- for (String possible : possibles) {
- if (s.equals(possible)) {
- return;
- }
- }
- Assert.assertTrue(false, "No potential match");
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void empty() throws Exception {
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
-
- encoder.encode(inputAttribute);
- }
-
- @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
- final int[] intArray = {1, 2, 3, 4};
- final var values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), new ScopedStringAttributeValue("foo",
- "bar"), new IdPAttributeValue<Object>() {
- @Override
- public Object getValue() {
- return intArray;
- }
- public String getDisplayValue() {
- return intArray.toString();
- }
- });
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- encoder.encode(inputAttribute);
- }
-
- @Test public void single() throws Exception {
- final var values = List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), ObjectFor(STRING_1));
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 1, "Encoding one entry");
- Assert.assertEquals(children.get(0).getElementQName(),
- AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- Assert.assertEquals(children.get(0).getOrderedChildren().size(), 1,
- "Expected exactly one child inside the <AttributeValue/>");
-
- CheckValues(children.get(0).getOrderedChildren().get(0), STRING_1);
- }
-
- @Test public void multi() throws Exception {
- final List<IdPAttributeValue<?>> values = List.of(ObjectFor(STRING_1), ObjectFor(STRING_2));
-
- final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
- inputAttribute.setValues(values);
-
- final Attribute outputAttribute = encoder.encode(inputAttribute);
- Assert.assertNotNull(outputAttribute);
-
- final List<XMLObject> children = outputAttribute.getOrderedChildren();
- Assert.assertEquals(children.size(), 2, "Encoding two entries");
-
- Assert.assertEquals(children.get(0).getElementQName(),
- AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- Assert.assertEquals(children.get(0).getOrderedChildren().size(), 1,
- "Expected exactly one child inside the <AttributeValue/> for first Attribute");
-
- Assert.assertEquals(children.get(1).getElementQName(),
- AttributeValue.DEFAULT_ELEMENT_NAME,
- "Attribute Value not inside <AttributeValue/>");
- Assert.assertEquals(children.get(1).getOrderedChildren().size(), 1,
- "Expected exactly one child inside the <AttributeValue/> for second Attribute");
-
- CheckValues(children.get(0).getOrderedChildren().get(0), STRING_1, STRING_2);
- CheckValues(children.get(1).getOrderedChildren().get(0), STRING_1, STRING_2);
-
- }
-
-}
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/AttributeValueMapperTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/AttributeValueMapperTest.java
deleted file mode 100644
index 45d515f..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/AttributeValueMapperTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import net.shibboleth.idp.attribute.EmptyAttributeValue;
-import net.shibboleth.idp.attribute.IdPAttributeValue;
-import net.shibboleth.idp.attribute.ByteAttributeValue;
-import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
-import net.shibboleth.idp.attribute.StringAttributeValue;
-import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
-import net.shibboleth.utilities.java.support.codec.Base64Support;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.ext.saml2mdui.UIInfo;
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-/**
- * Tests for AttributeValueMapper.
- */
-public class AttributeValueMapperTest extends MappingTests {
-
- private List<RequestedAttribute> attributes;
-
- private void loadAttributes() {
- if (null != attributes) {
- return;
- }
- attributes = loadFile("requestedAttributeValues.xml");
- }
-
- private List<XMLObject> getValues(String attributeName) {
- loadAttributes();
- for (RequestedAttribute attribute : attributes) {
- if (attributeName.equals(attribute.getName())) {
- return attribute.getAttributeValues();
- }
- }
- return null;
- }
-
- @Test public void testString() throws ComponentInitializationException {
-
- final StringAttributeValueMapper mapper = new StringAttributeValueMapper();
-
- mapper.setLogPrefix("testString");
- mapper.initialize();
- final List<IdPAttributeValue<?>> result = mapper.decodeValues(getValues("stdFormat"));
-
- Assert.assertEquals(result.size(), 4);
- final Set<String> strings = new HashSet(4);
-
- for (IdPAttributeValue val : result) {
- strings.add(((StringAttributeValue) val).getValue());
- }
- Assert.assertTrue(strings.contains("String"));
- Assert.assertTrue(strings.contains("1"));
- Assert.assertTrue(strings.contains("U2NvdCBDYW50b3IgaXMgdGhlIGdvZCBvZiBTQU1M"));
- Assert.assertTrue(strings.contains("scope at scoped.example.org"));
- }
-
- @Test public void testScopedString() throws ComponentInitializationException {
-
- ScopedStringAttributeValueMapper mapper = new ScopedStringAttributeValueMapper();
-
- mapper.setLogPrefix("testScopedString");
- mapper.initialize();
- List<IdPAttributeValue<?>> result = mapper.decodeValues(getValues("stdFormat"));
- Assert.assertEquals(result.size(), 1);
- ScopedStringAttributeValue value = (ScopedStringAttributeValue) result.get(0);
- Assert.assertEquals(value.getValue(), "scope");
- Assert.assertEquals(value.getScope(), "scoped.example.org");
-
- mapper = new ScopedStringAttributeValueMapper();
- mapper.setDelimiter("0b3IgaX");
- mapper.setLogPrefix("testScopedString2");
- mapper.initialize();
- result = mapper.decodeValues(getValues("stdFormat"));
- Assert.assertEquals(result.size(), 1);
- value = (ScopedStringAttributeValue) result.get(0);
- Assert.assertEquals(value.getValue(), "U2NvdCBDYW5");
- Assert.assertEquals(value.getScope(), "MgdGhlIGdvZCBvZiBTQU1M");
-
- result = mapper.decodeValues(getValues("urn:oid:0.9.2342.19200300.100.1.3"));
- Assert.assertTrue(result.isEmpty());
- }
-
- @Test public void testByte() throws ComponentInitializationException {
-
- ByteAttributeValueMapper mapper = new ByteAttributeValueMapper();
-
- mapper.setLogPrefix("testByte");
- mapper.initialize();
- final List<IdPAttributeValue<?>> result = mapper.decodeValues(getValues("stdFormat"));
- Assert.assertEquals(result.size(), 4);
- final Set<String> strings = new HashSet(4);
-
- for (IdPAttributeValue<?> val: result) {
- if (val instanceof EmptyAttributeValue) {
- strings.add(Base64Support.encode(new byte[0], Base64Support.CHUNKED));
- } else {
- strings.add(Base64Support.encode(((ByteAttributeValue)val).getValue(), Base64Support.CHUNKED));
- }
- }
- Assert.assertTrue(strings.contains("U2NvdCBDYW50b3IgaXMgdGhlIGdvZCBvZiBTQU1M"));
- }
-
- @Test public void testXMLObject() throws ComponentInitializationException {
-
- XMLObjectAttributeValueMapper mapper = new XMLObjectAttributeValueMapper();
-
- mapper.setLogPrefix("testXMLObject");
- mapper.initialize();
- final List<IdPAttributeValue<?>> result = mapper.decodeValues(getValues("stdFormat"));
- Assert.assertEquals(result.size(), 1);
- XMLObject object = ((XMLObjectAttributeValue) result.get(0)).getValue();
-
- Assert.assertTrue(object instanceof UIInfo);
- }
-}
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/MappingTests.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/MappingTests.java
deleted file mode 100644
index 5de81a8..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/MappingTests.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import java.util.List;
-
-import org.opensaml.core.xml.XMLObjectBaseTestCase;
-import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
-
-/**
- * Base class for testing attribute mapping
- */
-public class MappingTests extends XMLObjectBaseTestCase {
-
- public static final String FILE_PATH = "/net/shibboleth/idp/saml/impl/attribute/mapping/";
-
- protected static final String THE_FORMAT = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
-
- protected static final String SAML_NAME_ONE = "stdFormat";
-
- protected static final String SAML_NAME_TWO = "oddFormat";
-
- protected static final String SAML_NAME_THREE = "urn:oid:2.16.840.1.113730.3.1.241";
-
- protected List<RequestedAttribute> loadFile(final String file)
- {
- AttributeConsumingService service = unmarshallElement(FILE_PATH + file);
-
- return service.getRequestAttributes();
- }
-
-
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/NativeSpringTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/NativeSpringTest.java
deleted file mode 100644
index 2743f10..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/NativeSpringTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import java.util.Collection;
-
-import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
-
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
-import org.springframework.context.support.GenericApplicationContext;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-/**
- * kicks the wheels tests.
- */
-public class NativeSpringTest {
-
- protected <Type> Type getBean(String fileName, Class<Type> claz) {
-
- GenericApplicationContext context = new GenericApplicationContext();
- try {
- SchemaTypeAwareXMLBeanDefinitionReader beanDefinitionReader =
- new SchemaTypeAwareXMLBeanDefinitionReader(context);
-
- beanDefinitionReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
- beanDefinitionReader.loadBeanDefinitions(fileName);
-
- context.refresh();
-
- Collection<Type> beans = context.getBeansOfType(claz).values();
- Assert.assertEquals(beans.size(), 1);
-
- return beans.iterator().next();
- } finally {
- context.close();
- }
- }
-
-
- @Test
- public void stringAttrValue() {
- RequestedAttributesMapper map = getBean(MappingTests.FILE_PATH + "attributesMapper.xml", RequestedAttributesMapper.class);
-
- LoggerFactory.getLogger(NativeSpringTest.class).debug(map.toString());
- }
-}
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributeMapperTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributeMapperTest.java
deleted file mode 100644
index b29f6db..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributeMapperTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-/**
- * Tests for {@link RequestedAttributeMapper}.
- */
-public class RequestedAttributeMapperTest extends MappingTests {
-
- private static final String ID = "atributeID";
-
- private List<RequestedAttribute> attributes;
-
- private void loadAttributes() {
- if (null != attributes) {
- return;
- }
- attributes = loadFile("requestedAttributeValues.xml");
- }
-
- private RequestedAttribute getAttr(String attributeName) {
- loadAttributes();
- for (RequestedAttribute attribute : attributes) {
- if (attributeName.equals(attribute.getName())) {
- return attribute;
- }
- }
- return null;
- }
-
- @Test public void setterGetterInit() throws ComponentInitializationException {
- final RequestedAttributeMapper mapper = new RequestedAttributeMapper();
-
- Assert.assertNull(mapper.getId());
- Assert.assertTrue(mapper.getAttributeIds().isEmpty());
- Assert.assertNull(mapper.getAttributeFormat());
- Assert.assertNull(mapper.getSAMLName());
- Assert.assertNull(mapper.getValueMapper());
-
- mapper.setId(ID);
- try {
- mapper.initialize();
- Assert.fail("SAML Name absent");
- } catch (ComponentInitializationException e) {
- // OK
- }
- mapper.setSAMLName(SAML_NAME_ONE);
-
- try {
- mapper.initialize();
- Assert.fail("Value Mapper absent");
- } catch (ComponentInitializationException e) {
- // OK
- }
- mapper.setValueMapper(new StringAttributeValueMapper());
-
- mapper.setAttributeIds(Collections.singletonList("one"));
- mapper.setAttributeFormat(THE_FORMAT);
-
- mapper.initialize();
- Assert.assertEquals(mapper.getId(), ID);
- Assert.assertEquals(mapper.getSAMLName(), SAML_NAME_ONE);
- Assert.assertEquals(mapper.getAttributeFormat(), THE_FORMAT);
-
- final List<String> list = mapper.getAttributeIds();
- Assert.assertEquals(list.size(), 1);
- Assert.assertEquals(list.get(0), "one");
-
- Assert.assertTrue(mapper.getValueMapper() instanceof StringAttributeValueMapper);
- }
-
- @Test public void mapAttributeFormat() throws ComponentInitializationException {
- RequestedAttributeMapper mapper = new RequestedAttributeMapper();
-
- mapper.setId(ID);
- mapper.setSAMLName(SAML_NAME_ONE);
- mapper.setValueMapper(new StringAttributeValueMapper());
- mapper.setAttributeIds(Arrays.asList("one", ID));
- mapper.setAttributeFormat(THE_FORMAT);
- mapper.initialize();
-
- final Map<String, IdPRequestedAttribute> result =
- mapper.mapAttribute(getAttr(SAML_NAME_ONE));
-
- Assert.assertEquals(result.size(), 2);
- Assert.assertTrue(result.containsKey(ID));
- Assert.assertTrue(result.containsKey("one"));
- Assert.assertNotNull(result.get(ID));
- Assert.assertNotNull(result.get("one"));
- Assert.assertEquals(result.get(ID).getValues().size(), 4);
-
- Assert.assertTrue(mapper.mapAttribute(getAttr(SAML_NAME_TWO)).isEmpty());
-
- mapper = new RequestedAttributeMapper();
-
- mapper.setId(ID);
- mapper.setSAMLName(SAML_NAME_TWO);
- mapper.setAttributeFormat(THE_FORMAT);
- mapper.setValueMapper(new StringAttributeValueMapper());
- mapper.setAttributeIds(Collections.singletonList(ID));
- mapper.initialize();
- Assert.assertTrue(mapper.mapAttribute(getAttr(SAML_NAME_TWO)).isEmpty());
-
- }
-
- @Test public void mapAttributeNoFormat() throws ComponentInitializationException {
- RequestedAttributeMapper mapper = new RequestedAttributeMapper();
-
- mapper.setId(ID);
- mapper.setAttributeIds(Collections.singletonList(ID));
- mapper.setSAMLName(SAML_NAME_TWO);
- mapper.setValueMapper(new StringAttributeValueMapper());
- mapper.initialize();
-
- Map<String, net.shibboleth.idp.attribute.IdPRequestedAttribute> result =
- mapper.mapAttribute(getAttr(SAML_NAME_TWO));
-
- Assert.assertEquals(result.size(), 1);
- Assert.assertTrue(result.get(ID).getValues().isEmpty());
-
- }
-
- @Test public void mapNoValueMatch() throws ComponentInitializationException {
- RequestedAttributeMapper mapper = new RequestedAttributeMapper();
-
- mapper.setId(ID);
- mapper.setAttributeIds(Collections.singletonList(ID));
- mapper.setSAMLName(SAML_NAME_THREE);
- mapper.setValueMapper(new ScopedStringAttributeValueMapper());
- mapper.initialize();
-
- Map<String, IdPRequestedAttribute> result =
- mapper.mapAttribute(getAttr(SAML_NAME_THREE));
- Assert.assertFalse(result.containsKey(ID));
- }
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributesMapperTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributesMapperTest.java
deleted file mode 100644
index 060277b..0000000
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/mapping/impl/RequestedAttributesMapperTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.idp.saml.attribute.mapping.impl;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-
-import net.shibboleth.idp.attribute.IdPRequestedAttribute;
-import net.shibboleth.idp.saml.attribute.mapping.AbstractSAMLAttributeValueMapper;
-import net.shibboleth.idp.saml.attribute.mapping.AttributeMapper;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-
-import org.opensaml.saml.saml2.metadata.RequestedAttribute;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Multimap;
-
-/**
- * tests for {@link RequestedAttributesMapper}.
- */
-public class RequestedAttributesMapperTest extends MappingTests {
-
- private AttributeMapper<RequestedAttribute, IdPRequestedAttribute> buildMapper(String name, String samlFormat, AbstractSAMLAttributeValueMapper mapper) {
-
- RequestedAttributeMapper result = new RequestedAttributeMapper();
- result.setId(name);
- result.setAttributeIds(Collections.singletonList(name));
- result.setSAMLName(samlFormat);
- result.setValueMapper(mapper);
- return result;
- }
-
-
- @Test public void setterGetter() throws ComponentInitializationException {
-
- RequestedAttributesMapper mapper = new RequestedAttributesMapper();
- mapper.setId("id");
- Assert.assertTrue(mapper.getMappers().isEmpty());
- mapper.setMappers(Collections.singletonList(buildMapper("name", "saml", new StringAttributeValueMapper())));
-
- mapper.initialize();
- }
-
-
- @Test public void map() throws ComponentInitializationException {
-
- RequestedAttributesMapper mapper = new RequestedAttributesMapper();
- mapper.setId("id");
-
- mapper.setMappers(Arrays.asList(buildMapper("id", SAML_NAME_ONE, new StringAttributeValueMapper()),
- buildMapper("id", SAML_NAME_THREE, new ScopedStringAttributeValueMapper()),
- buildMapper("id2", SAML_NAME_THREE, new StringAttributeValueMapper())));
-
- mapper.initialize();
-
- Multimap<String, IdPRequestedAttribute> result = mapper.mapAttributes(loadFile("requestedAttributeValues.xml"));
-
- Assert.assertEquals(result.keySet().size(), 2);
-
- Collection<IdPRequestedAttribute> id = result.get("id");
- Assert.assertEquals(id.size(), 1);
- Iterator<IdPRequestedAttribute> itr = id.iterator();
- Assert.assertEquals(itr.next().getId(), "id");
-
- Assert.assertEquals(result.get("id2").size(), 1);
- }
-}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoderTest.java
new file mode 100644
index 0000000..ebce4b8
--- /dev/null
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoderTest.java
@@ -0,0 +1,368 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.ByteAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
+import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.utilities.java.support.codec.Base64Support;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+import org.opensaml.core.OpenSAMLInitBaseTestCase;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.XMLObjectBuilder;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSBase64Binary;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml1.core.Attribute;
+import org.opensaml.saml.saml1.core.AttributeValue;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/** {@link SAML1ByteAttributeTranscoder} unit test. */
+public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
+
+ private AttributeTranscoderRegistryImpl registry;
+
+ private XMLObjectBuilder<XSString> stringBuilder;
+
+ private SAMLObjectBuilder<Attribute> attributeBuilder;
+
+ private SAMLObjectBuilder<AttributeDesignator> designatorBuilder;
+
+ private final static String ATTR_NAME = "foo";
+ private final static String ATTR_NAMESPACE = "Namespace";
+ private final static byte[] BYTE_ARRAY_1 = {1, 2, 3, 4, 5};
+ private final static byte[] BYTE_ARRAY_2 = {4, 3, 2, 1};
+
+ @BeforeClass public void setUp() throws ComponentInitializationException {
+
+ stringBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
+
+ attributeBuilder = (SAMLObjectBuilder<Attribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
+ Attribute.TYPE_NAME);
+ designatorBuilder = (SAMLObjectBuilder<AttributeDesignator>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<AttributeDesignator>getBuilderOrThrow(
+ AttributeDesignator.TYPE_NAME);
+
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ final SAML1ByteAttributeTranscoder transcoder = new SAML1ByteAttributeTranscoder();
+ transcoder.initialize();
+
+ registry.setNamingRegistry(Collections.singletonMap(transcoder.getEncodedType(),
+ new AbstractSAML1AttributeTranscoder.NamingFunction()));
+
+ final Map<String,Object> ruleset1 = new HashMap<>();
+ ruleset1.put(AttributeTranscoderRegistry.PROP_ID, ATTR_NAME);
+ ruleset1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_ENCODE_TYPE, true);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_NAME, ATTR_NAME);
+ ruleset1.put(SAML1AttributeTranscoder.PROP_NAMESPACE, ATTR_NAMESPACE);
+
+ registry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(ruleset1)));
+
+ registry.initialize();
+ }
+
+ @AfterClass public void tearDown() {
+ registry.destroy();
+ registry = null;
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void emptyEncode() throws Exception {
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void emptyRequestedEncode() throws Exception {
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, AttributeDesignator.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
+ null, inputAttribute, AttributeDesignator.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getAttributeName(), ATTR_NAME);
+ Assert.assertEquals(attr.getAttributeNamespace(), ATTR_NAMESPACE);
+ }
+
+ @Test public void emptyDecode() throws Exception {
+
+ // This isn't technically legal in SAML, but it should functionally work in this direction.
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test public void emptyRequestedDecode() throws Exception {
+
+ final AttributeDesignator samlAttribute = designatorBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertFalse(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
+ final int[] intArray = {1, 2, 3, 4};
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new StringAttributeValue("foo"), new ScopedStringAttributeValue("foo", "bar"),
+ new IdPAttributeValue<Object>() {
+ public Object getValue() {
+ return intArray;
+ }
+ public String getDisplayValue() {
+ return intArray.toString();
+ }
+ });
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void single() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new StringAttributeValue("foo"), new ByteAttributeValue(BYTE_ARRAY_1));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getAttributeName(), ATTR_NAME);
+ Assert.assertEquals(attr.getAttributeNamespace(), ATTR_NAMESPACE);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+
+ final XMLObject child = children.get(0);
+
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
+
+ XSBase64Binary childAsString = (XSBase64Binary) child;
+
+ byte childAsBa[] = Base64Support.decode(childAsString.getValue());
+
+ Assert.assertEquals(childAsBa, BYTE_ARRAY_1, "Input equals output");
+ }
+
+ @Test public void singleRequested() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new StringAttributeValue("foo"), new ByteAttributeValue(BYTE_ARRAY_1));
+
+ final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
+ null, inputAttribute, AttributeDesignator.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getAttributeName(), ATTR_NAME);
+ Assert.assertEquals(attr.getAttributeNamespace(), ATTR_NAMESPACE);
+ }
+
+ @Test public void singleDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(Base64Support.encode(BYTE_ARRAY_1, Base64Support.UNCHUNKED));
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 1);
+ Assert.assertEquals(attr.getValues().get(0).getValue(), BYTE_ARRAY_1);
+ }
+
+ @Test(expectedExceptions = {AttributeDecodingException.class,}) public void badDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue("******");
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+ }
+
+ @Test public void multi() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(BYTE_ARRAY_1), new ByteAttributeValue(BYTE_ARRAY_2));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+ Assert.assertEquals(children.size(), 2, "Encoding three entries");
+
+ XMLObject child = children.get(0);
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
+
+ XSBase64Binary childAsString = (XSBase64Binary) child;
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ final byte[] res0 = Base64Support.decode(childAsString.getValue());
+
+ child = children.get(1);
+ Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
+
+ childAsString = (XSBase64Binary) child;
+ final byte[] res1 = Base64Support.decode(childAsString.getValue());
+
+ //
+ // order of results is not guaranteed so sense the result from the length
+ //
+ if (BYTE_ARRAY_1.length == res0.length) {
+ Assert.assertEquals(BYTE_ARRAY_1, res0, "Input matches output");
+ Assert.assertEquals(BYTE_ARRAY_2, res1, "Input matches output");
+ } else if (BYTE_ARRAY_1.length == res1.length) {
+ Assert.assertEquals(BYTE_ARRAY_1, res1, "Input matches output");
+ Assert.assertEquals(BYTE_ARRAY_2, res0, "Input matches output");
+ } else {
+ Assert.assertTrue(BYTE_ARRAY_1.length == res1.length || BYTE_ARRAY_2.length == res1.length,
+ "One of the output's size should match an input size");
+ }
+ }
+
+ @Test public void multiDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(Base64Support.encode(BYTE_ARRAY_1, Base64Support.UNCHUNKED));
+
+ final XSString stringValue2 = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue2.setValue(Base64Support.encode(BYTE_ARRAY_2, Base64Support.UNCHUNKED));
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+ samlAttribute.getAttributeValues().add(stringValue);
+ samlAttribute.getAttributeValues().add(stringValue2);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 2);
+ Assert.assertEquals(attr.getValues().get(0).getValue(), BYTE_ARRAY_1);
+ Assert.assertEquals(attr.getValues().get(1).getValue(), BYTE_ARRAY_2);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoderTest.java
new file mode 100644
index 0000000..1071168
--- /dev/null
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoderTest.java
@@ -0,0 +1,370 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.ByteAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
+import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.xmlobject.ScopedValue;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+import org.opensaml.core.OpenSAMLInitBaseTestCase;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.XMLObjectBuilder;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml1.core.Attribute;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
+import org.opensaml.saml.saml1.core.AttributeValue;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/** {@link SAML1ScopedStringAttributeTranscoder} unit test. */
+public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
+
+ private AttributeTranscoderRegistryImpl registry;
+
+ private XMLObjectBuilder<XSString> stringBuilder;
+
+ private XMLObjectBuilder<ScopedValue> scopedBuilder;
+
+ private SAMLObjectBuilder<Attribute> attributeBuilder;
+
+ private SAMLObjectBuilder<AttributeDesignator> designatorBuilder;
+
+ private final static String ATTR_NAME = "foo";
+ private final static String ATTR_NAMESPACE = "Namespace";
+ private final static String STRING_1 = "Value The First";
+ private final static String STRING_2 = "Second string the value is";
+ private final static String SCOPE_1 = "scope1.example.org";
+ private final static String SCOPE_2 = "scope2";
+ private final static String DELIMITER = "#";
+
+ @BeforeClass public void setUp() throws ComponentInitializationException {
+
+ stringBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(
+ XSString.TYPE_NAME);
+
+ scopedBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<ScopedValue>getBuilderOrThrow(
+ ScopedValue.TYPE_NAME);
+
+ attributeBuilder = (SAMLObjectBuilder<Attribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
+ Attribute.TYPE_NAME);
+ designatorBuilder = (SAMLObjectBuilder<AttributeDesignator>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<AttributeDesignator>getBuilderOrThrow(
+ AttributeDesignator.TYPE_NAME);
+
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ final SAML1ScopedStringAttributeTranscoder transcoder = new SAML1ScopedStringAttributeTranscoder();
+ transcoder.initialize();
+
+ registry.setNamingRegistry(Collections.singletonMap(transcoder.getEncodedType(),
+ new AbstractSAML1AttributeTranscoder.NamingFunction()));
+
+ final Map<String,Object> ruleset1 = new HashMap<>();
+ ruleset1.put(AttributeTranscoderRegistry.PROP_ID, ATTR_NAME);
+ ruleset1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_ENCODE_TYPE, true);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_NAME, ATTR_NAME);
+ ruleset1.put(SAML1AttributeTranscoder.PROP_NAMESPACE, ATTR_NAMESPACE);
+ ruleset1.put(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER, DELIMITER);
+ ruleset1.put(SAML1ScopedStringAttributeTranscoder.PROP_SCOPE_TYPE, "attribute");
+
+ registry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(ruleset1)));
+
+ registry.initialize();
+ }
+
+ @AfterClass public void tearDown() {
+ registry.destroy();
+ registry = null;
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void emptyEncode() throws Exception {
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void emptyDecode() throws Exception {
+
+ // This isn't technically legal in SAML, but it should functionally work in this direction.
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test public void emptyRequestedDecode() throws Exception {
+
+ final AttributeDesignator samlAttribute = designatorBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertFalse(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
+ final int[] intArray = {1, 2, 3, 4};
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue<Object>() {
+ @Override
+ public Object getValue() {
+ return intArray;
+ }
+ @Override
+ public String getDisplayValue() {
+ return intArray.toString();
+ }
+ });
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void single() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
+ new ScopedStringAttributeValue(STRING_1, SCOPE_1),
+ new StringAttributeValue(STRING_1),
+ new StringAttributeValue(STRING_1 + "@" + SCOPE_1));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getAttributeName(), ATTR_NAME);
+ Assert.assertEquals(attr.getAttributeNamespace(), ATTR_NAMESPACE);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+
+ final XMLObject child = children.get(0);
+
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+
+ Assert.assertTrue(child instanceof ScopedValue, "Child of result attribute should be a string");
+
+ final ScopedValue childAsScopedValue = (ScopedValue) child;
+
+ Assert.assertEquals(childAsScopedValue.getValue(), STRING_1, "Input equals output");
+ Assert.assertEquals(childAsScopedValue.getScope(), SCOPE_1, "Input equals output");
+ }
+
+ @Test public void singleRequested() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
+ new ScopedStringAttributeValue(STRING_1, SCOPE_1));
+
+ final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
+ null, inputAttribute, AttributeDesignator.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getAttributeName(), ATTR_NAME);
+ Assert.assertEquals(attr.getAttributeNamespace(), ATTR_NAMESPACE);
+ }
+
+ @Test public void singleDecode() throws Exception {
+
+ final ScopedValue scopedValue = scopedBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ scopedValue.setScopeAttributeName("Scope");
+ scopedValue.setValue(STRING_1);
+ scopedValue.setScope(SCOPE_1);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+ samlAttribute.getAttributeValues().add(scopedValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 1);
+
+ final ScopedStringAttributeValue value = (ScopedStringAttributeValue) attr.getValues().get(0);
+ Assert.assertEquals(value.getValue(), STRING_1);
+ Assert.assertEquals(value.getScope(), SCOPE_1);
+ }
+
+ @Test public void multi() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
+ new ScopedStringAttributeValue(STRING_1, SCOPE_1),
+ new ScopedStringAttributeValue(STRING_2, SCOPE_2));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+ Assert.assertEquals(children.size(), 2, "Encoding 2 entries");
+
+ Assert.assertTrue(children.get(0) instanceof ScopedValue && children.get(1) instanceof ScopedValue,
+ "Child of result attribute should be a string");
+
+ final ScopedValue child1 = (ScopedValue) children.get(0);
+ Assert.assertEquals(child1.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+
+ final ScopedValue child2 = (ScopedValue) children.get(1);
+ Assert.assertEquals(child2.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ //
+ // order of results is not guaranteed so sense the result from the length
+ //
+ if (child1.getValue().length() == STRING_1.length()) {
+ Assert.assertEquals(child1.getValue(), STRING_1, "Input matches output");
+ Assert.assertEquals(child2.getValue(), STRING_2, "Input matches output");
+ Assert.assertEquals(child1.getScope(), SCOPE_1, "Input matches output");
+ Assert.assertEquals(child2.getScope(), SCOPE_2, "Input matches output");
+ } else if (child1.getValue().length() == STRING_2.length()) {
+ Assert.assertEquals(child2.getValue(), STRING_1, "Input matches output");
+ Assert.assertEquals(child1.getValue(), STRING_2, "Input matches output");
+ Assert.assertEquals(child2.getScope(), SCOPE_1, "Input matches output");
+ Assert.assertEquals(child1.getScope(), SCOPE_2, "Input matches output");
+ } else {
+ Assert.fail("Value mismatch");
+ }
+ }
+
+ @Test public void multiDecode() throws Exception {
+
+ final ScopedValue scopedValue = scopedBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ scopedValue.setScopeAttributeName("Scope");
+ scopedValue.setValue(STRING_1);
+ scopedValue.setScope(SCOPE_1);
+
+ final ScopedValue scopedValue2 = scopedBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ scopedValue2.setScopeAttributeName("Scope");
+ scopedValue2.setValue(STRING_2);
+ scopedValue2.setScope(SCOPE_2);
+
+ final XSString stringValue3 = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue3.setValue(STRING_2 + "@" + SCOPE_2);
+
+ final XSString stringValue4 = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue4.setValue(STRING_2);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+ samlAttribute.getAttributeValues().add(scopedValue);
+ samlAttribute.getAttributeValues().add(scopedValue2);
+ samlAttribute.getAttributeValues().add(stringValue3);
+ samlAttribute.getAttributeValues().add(stringValue4);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 2);
+
+ final ScopedStringAttributeValue value1 = (ScopedStringAttributeValue) attr.getValues().get(0);
+ final ScopedStringAttributeValue value2 = (ScopedStringAttributeValue) attr.getValues().get(1);
+ Assert.assertTrue(STRING_1.equals(value1.getValue()) || STRING_1.equals(value2.getValue()));
+ Assert.assertTrue(STRING_2.equals(value1.getValue()) || STRING_2.equals(value2.getValue()));
+ Assert.assertTrue(SCOPE_1.equals(value1.getScope()) || SCOPE_1.equals(value2.getScope()));
+ Assert.assertTrue(SCOPE_2.equals(value1.getScope()) || SCOPE_2.equals(value2.getScope()));
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoderTest.java
new file mode 100644
index 0000000..ad33578
--- /dev/null
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoderTest.java
@@ -0,0 +1,327 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.ByteAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
+import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+import org.opensaml.core.OpenSAMLInitBaseTestCase;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.XMLObjectBuilder;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml1.core.Attribute;
+import org.opensaml.saml.saml1.core.AttributeValue;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/** {@link SAML1StringAttributeTranscoder} unit test. */
+public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
+
+ private AttributeTranscoderRegistryImpl registry;
+
+ private XMLObjectBuilder<XSString> stringBuilder;
+
+ private SAMLObjectBuilder<Attribute> attributeBuilder;
+
+ private SAMLObjectBuilder<AttributeDesignator> designatorBuilder;
+
+ private final static String ATTR_NAME = "foo";
+ private final static String ATTR_NAMESPACE = "Namespace";
+ private final static String STRING_1 = "Value The First";
+ private final static String STRING_2 = "Second string the value is";
+
+ @BeforeClass public void setUp() throws ComponentInitializationException {
+
+ stringBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
+
+ attributeBuilder = (SAMLObjectBuilder<Attribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
+ Attribute.TYPE_NAME);
+ designatorBuilder = (SAMLObjectBuilder<AttributeDesignator>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<AttributeDesignator>getBuilderOrThrow(
+ AttributeDesignator.TYPE_NAME);
+
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ final SAML1StringAttributeTranscoder transcoder = new SAML1StringAttributeTranscoder();
+ transcoder.initialize();
+
+ registry.setNamingRegistry(Collections.singletonMap(transcoder.getEncodedType(),
+ new AbstractSAML1AttributeTranscoder.NamingFunction()));
+
+ final Map<String,Object> ruleset1 = new HashMap<>();
+ ruleset1.put(AttributeTranscoderRegistry.PROP_ID, ATTR_NAME);
+ ruleset1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_ENCODE_TYPE, true);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_NAME, ATTR_NAME);
+ ruleset1.put(SAML1AttributeTranscoder.PROP_NAMESPACE, ATTR_NAMESPACE);
+
+ registry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(ruleset1)));
+
+ registry.initialize();
+ }
+
+ @AfterClass public void tearDown() {
+ registry.destroy();
+ registry = null;
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void emptyEncode() throws Exception {
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void emptyRequestedEncode() throws Exception {
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, AttributeDesignator.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
+ null, inputAttribute, AttributeDesignator.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getAttributeName(), ATTR_NAME);
+ Assert.assertEquals(attr.getAttributeNamespace(), ATTR_NAMESPACE);
+ }
+
+ @Test public void emptyDecode() throws Exception {
+
+ // This isn't technically legal in SAML, but it should functionally work in this direction.
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test public void emptyRequestedDecode() throws Exception {
+
+ final AttributeDesignator samlAttribute = designatorBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertFalse(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
+ final int[] intArray = {1, 2, 3, 4};
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue<Object>() {
+ @Override
+ public Object getValue() {
+ return intArray;
+ }
+ @Override
+ public String getDisplayValue() {
+ return intArray.toString();
+ }
+ });
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void single() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getAttributeName(), ATTR_NAME);
+ Assert.assertEquals(attr.getAttributeNamespace(), ATTR_NAMESPACE);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+
+ final XMLObject child = children.get(0);
+
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+
+ Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
+
+ final XSString childAsString = (XSString) child;
+
+ Assert.assertEquals(childAsString.getValue(), STRING_1);
+ }
+
+ @Test public void singleRequested() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
+
+ final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
+ null, inputAttribute, AttributeDesignator.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getAttributeName(), ATTR_NAME);
+ Assert.assertEquals(attr.getAttributeNamespace(), ATTR_NAMESPACE);
+ }
+
+ @Test public void singleDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(STRING_1);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 1);
+ Assert.assertEquals(attr.getValues().get(0).getValue().toString(), STRING_1);
+ }
+
+ @Test public void multi() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
+ new StringAttributeValue(STRING_1),
+ new StringAttributeValue(STRING_2),
+ new ScopedStringAttributeValue(STRING_1, STRING_2));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+ Assert.assertEquals(children.size(), 3, "Encoding three entries");
+
+ for (final XMLObject child: children) {
+ Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
+ final String childAsString = ((XSString) children.get(0)).getValue();
+ Assert.assertTrue(STRING_1.equals(childAsString)||STRING_2.equals(childAsString));
+ }
+ }
+
+ @Test public void multiDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(STRING_1);
+
+ final XSString stringValue2 = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue2.setValue(STRING_2);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setAttributeName(ATTR_NAME);
+ samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
+ samlAttribute.getAttributeValues().add(stringValue);
+ samlAttribute.getAttributeValues().add(stringValue2);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 2);
+ Assert.assertEquals(attr.getValues().get(0).getValue().toString(), STRING_1);
+ Assert.assertEquals(attr.getValues().get(1).getValue().toString(), STRING_2);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoderTest.java
new file mode 100644
index 0000000..203a93c
--- /dev/null
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoderTest.java
@@ -0,0 +1,405 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.ByteAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
+import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.utilities.java.support.codec.Base64Support;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+import org.opensaml.core.OpenSAMLInitBaseTestCase;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.XMLObjectBuilder;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSBase64Binary;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeValue;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/** {@link SAML2ByteAttributeTranscoder} unit test. */
+public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
+
+ private AttributeTranscoderRegistryImpl registry;
+
+ private XMLObjectBuilder<XSString> stringBuilder;
+
+ private SAMLObjectBuilder<Attribute> attributeBuilder;
+
+ private SAMLObjectBuilder<RequestedAttribute> reqAttributeBuilder;
+
+ private final static String ATTR_NAME = "foo";
+ private final static String ATTR_NAMEFORMAT = "Namespace";
+ private final static String ATTR_FRIENDLYNAME = "friendly";
+ private final static byte[] BYTE_ARRAY_1 = {1, 2, 3, 4, 5};
+ private final static byte[] BYTE_ARRAY_2 = {4, 3, 2, 1};
+
+ @BeforeClass public void setUp() throws ComponentInitializationException {
+
+ stringBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
+
+ attributeBuilder = (SAMLObjectBuilder<Attribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
+ Attribute.TYPE_NAME);
+ reqAttributeBuilder = (SAMLObjectBuilder<RequestedAttribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<RequestedAttribute>getBuilderOrThrow(
+ RequestedAttribute.TYPE_NAME);
+
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ final SAML2ByteAttributeTranscoder transcoder = new SAML2ByteAttributeTranscoder();
+ transcoder.initialize();
+
+ registry.setNamingRegistry(Collections.singletonMap(transcoder.getEncodedType(),
+ new AbstractSAML2AttributeTranscoder.NamingFunction()));
+
+ final Map<String,Object> ruleset1 = new HashMap<>();
+ ruleset1.put(AttributeTranscoderRegistry.PROP_ID, ATTR_NAME);
+ ruleset1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_ENCODE_TYPE, true);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_NAME, ATTR_NAME);
+ ruleset1.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT, ATTR_NAMEFORMAT);
+ ruleset1.put(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME, ATTR_FRIENDLYNAME);
+
+ registry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(ruleset1)));
+
+ registry.initialize();
+ }
+
+ @AfterClass public void tearDown() {
+ registry.destroy();
+ registry = null;
+ }
+
+ @Test public void emptyEncode() throws Exception {
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+ Assert.assertTrue(attr.getAttributeValues().isEmpty());
+ }
+
+ @Test public void emptyDecode() throws Exception {
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test public void emptyRequestedDecode() throws Exception {
+
+ final RequestedAttribute samlAttribute = reqAttributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.setIsRequired(true);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
+ final int[] intArray = {1, 2, 3, 4};
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new StringAttributeValue("foo"), new ScopedStringAttributeValue("foo", "bar"),
+ new IdPAttributeValue<Object>() {
+ public Object getValue() {
+ return intArray;
+ }
+ public String getDisplayValue() {
+ return intArray.toString();
+ }
+ });
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void single() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new StringAttributeValue("foo"), new ByteAttributeValue(BYTE_ARRAY_1));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+
+ final XMLObject child = children.get(0);
+
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
+
+ XSBase64Binary childAsString = (XSBase64Binary) child;
+
+ byte childAsBa[] = Base64Support.decode(childAsString.getValue());
+
+ Assert.assertEquals(childAsBa, BYTE_ARRAY_1, "Input equals output");
+ }
+
+ @Test public void singleRequested() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new StringAttributeValue("foo"), new ByteAttributeValue(BYTE_ARRAY_1));
+
+ final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
+ inputAttribute.setRequired(true);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final RequestedAttribute attr = TranscoderSupport.<RequestedAttribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, RequestedAttribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+ Assert.assertTrue(attr.isRequired());
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+
+ final XMLObject child = children.get(0);
+
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
+
+ XSBase64Binary childAsString = (XSBase64Binary) child;
+
+ byte childAsBa[] = Base64Support.decode(childAsString.getValue());
+
+ Assert.assertEquals(childAsBa, BYTE_ARRAY_1, "Input equals output");
+ }
+
+ @Test public void singleDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(Base64Support.encode(BYTE_ARRAY_1, Base64Support.UNCHUNKED));
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 1);
+ Assert.assertEquals(attr.getValues().get(0).getValue(), BYTE_ARRAY_1);
+ }
+
+ @Test(expectedExceptions = {AttributeDecodingException.class,}) public void badDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue("******");
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+ }
+
+ @Test public void singleRequestedDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(Base64Support.encode(BYTE_ARRAY_1, Base64Support.UNCHUNKED));
+
+ final RequestedAttribute samlAttribute = reqAttributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.setIsRequired(true);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertEquals(attr.getValues().size(), 1);
+ Assert.assertEquals(attr.getValues().get(0).getValue(), BYTE_ARRAY_1);
+ }
+
+ @Test public void multi() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(BYTE_ARRAY_1), new ByteAttributeValue(BYTE_ARRAY_2));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+ Assert.assertEquals(children.size(), 2, "Encoding three entries");
+
+ XMLObject child = children.get(0);
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
+
+ XSBase64Binary childAsString = (XSBase64Binary) child;
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ final byte[] res0 = Base64Support.decode(childAsString.getValue());
+
+ child = children.get(1);
+ Assert.assertTrue(child instanceof XSBase64Binary, "Child of result attribute should be a base64Binary");
+
+ childAsString = (XSBase64Binary) child;
+ final byte[] res1 = Base64Support.decode(childAsString.getValue());
+
+ //
+ // order of results is not guaranteed so sense the result from the length
+ //
+ if (BYTE_ARRAY_1.length == res0.length) {
+ Assert.assertEquals(BYTE_ARRAY_1, res0, "Input matches output");
+ Assert.assertEquals(BYTE_ARRAY_2, res1, "Input matches output");
+ } else if (BYTE_ARRAY_1.length == res1.length) {
+ Assert.assertEquals(BYTE_ARRAY_1, res1, "Input matches output");
+ Assert.assertEquals(BYTE_ARRAY_2, res0, "Input matches output");
+ } else {
+ Assert.assertTrue(BYTE_ARRAY_1.length == res1.length || BYTE_ARRAY_2.length == res1.length,
+ "One of the output's size should match an input size");
+ }
+ }
+
+ @Test public void multiDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(Base64Support.encode(BYTE_ARRAY_1, Base64Support.UNCHUNKED));
+
+ final XSString stringValue2 = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue2.setValue(Base64Support.encode(BYTE_ARRAY_2, Base64Support.UNCHUNKED));
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.getAttributeValues().add(stringValue);
+ samlAttribute.getAttributeValues().add(stringValue2);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 2);
+ Assert.assertEquals(attr.getValues().get(0).getValue(), BYTE_ARRAY_1);
+ Assert.assertEquals(attr.getValues().get(1).getValue(), BYTE_ARRAY_2);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoderTest.java
new file mode 100644
index 0000000..05d1b7c
--- /dev/null
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoderTest.java
@@ -0,0 +1,394 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.ByteAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
+import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+import org.opensaml.core.OpenSAMLInitBaseTestCase;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.XMLObjectBuilder;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeValue;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/** {@link SAML2ScopedStringAttributeTranscoder} unit test. */
+public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
+
+ private AttributeTranscoderRegistryImpl registry;
+
+ private XMLObjectBuilder<XSString> stringBuilder;
+
+ private SAMLObjectBuilder<Attribute> attributeBuilder;
+
+ private SAMLObjectBuilder<RequestedAttribute> reqAttributeBuilder;
+
+ private final static String ATTR_NAME = "foo";
+ private final static String ATTR_NAMEFORMAT = "Namespace";
+ private final static String ATTR_FRIENDLYNAME = "friendly";
+ private final static String STRING_1 = "Value The First";
+ private final static String STRING_2 = "Second string the value is";
+ private final static String SCOPE_1 = "scope1.example.org";
+ private final static String SCOPE_2 = "scope2";
+ private final static String DELIMITER = "#";
+
+ @BeforeClass public void setUp() throws ComponentInitializationException {
+
+ stringBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
+
+ attributeBuilder = (SAMLObjectBuilder<Attribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
+ Attribute.TYPE_NAME);
+ reqAttributeBuilder = (SAMLObjectBuilder<RequestedAttribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<RequestedAttribute>getBuilderOrThrow(
+ RequestedAttribute.TYPE_NAME);
+
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ final SAML2ScopedStringAttributeTranscoder transcoder = new SAML2ScopedStringAttributeTranscoder();
+ transcoder.initialize();
+
+ registry.setNamingRegistry(Collections.singletonMap(transcoder.getEncodedType(),
+ new AbstractSAML2AttributeTranscoder.NamingFunction()));
+
+ final Map<String,Object> ruleset1 = new HashMap<>();
+ ruleset1.put(AttributeTranscoderRegistry.PROP_ID, ATTR_NAME);
+ ruleset1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_ENCODE_TYPE, true);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_NAME, ATTR_NAME);
+ ruleset1.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT, ATTR_NAMEFORMAT);
+ ruleset1.put(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME, ATTR_FRIENDLYNAME);
+ ruleset1.put(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER, DELIMITER);
+ ruleset1.put(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_TYPE, "inline");
+
+ registry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(ruleset1)));
+
+ registry.initialize();
+ }
+
+ @AfterClass public void tearDown() {
+ registry.destroy();
+ registry = null;
+ }
+
+ @Test public void emptyEncode() throws Exception {
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+ Assert.assertTrue(attr.getAttributeValues().isEmpty());
+ }
+
+ @Test public void emptyDecode() throws Exception {
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test public void emptyRequestedDecode() throws Exception {
+
+ final RequestedAttribute samlAttribute = reqAttributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.setIsRequired(true);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
+ final int[] intArray = {1, 2, 3, 4};
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue<Object>() {
+ @Override
+ public Object getValue() {
+ return intArray;
+ }
+ @Override
+ public String getDisplayValue() {
+ return intArray.toString();
+ }
+ });
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void single() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
+ new ScopedStringAttributeValue(STRING_1, SCOPE_1),
+ new StringAttributeValue(STRING_1),
+ new StringAttributeValue(STRING_1 + "@" + SCOPE_1));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+
+ final XMLObject child = children.get(0);
+
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+
+ Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
+
+ final XSString childAsString = (XSString) child;
+
+ Assert.assertEquals(childAsString.getValue(), STRING_1 + DELIMITER + SCOPE_1);
+ }
+
+ @Test public void singleRequested() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
+ new ScopedStringAttributeValue(STRING_1, SCOPE_1));
+
+ final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
+ inputAttribute.setRequired(true);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final RequestedAttribute attr = TranscoderSupport.<RequestedAttribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, RequestedAttribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+ Assert.assertTrue(attr.isRequired());
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+
+ final XMLObject child = children.get(0);
+
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+
+ Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
+
+ final XSString childAsString = (XSString) child;
+
+ Assert.assertEquals(childAsString.getValue(), STRING_1 + DELIMITER + SCOPE_1);
+ }
+
+ @Test public void singleDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(STRING_1 + DELIMITER + SCOPE_1);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 1);
+
+ final ScopedStringAttributeValue value = (ScopedStringAttributeValue) attr.getValues().get(0);
+ Assert.assertEquals(value.getValue(), STRING_1);
+ Assert.assertEquals(value.getScope(), SCOPE_1);
+ }
+
+
+ @Test public void singleRequestedDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(STRING_1 + DELIMITER + SCOPE_1);
+
+ final RequestedAttribute samlAttribute = reqAttributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.setIsRequired(true);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertEquals(attr.getValues().size(), 1);
+
+ final ScopedStringAttributeValue value = (ScopedStringAttributeValue) attr.getValues().get(0);
+ Assert.assertEquals(value.getValue(), STRING_1);
+ Assert.assertEquals(value.getScope(), SCOPE_1);
+ }
+
+ @Test public void multi() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
+ new ScopedStringAttributeValue(STRING_1, SCOPE_1),
+ new ScopedStringAttributeValue(STRING_2, SCOPE_2));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+ Assert.assertEquals(children.size(), 2, "Encoding 2 entries");
+
+ final String s1 = STRING_1 + DELIMITER + SCOPE_1;
+ final String s2 = STRING_2 + DELIMITER + SCOPE_2;
+
+ for (final XMLObject child: children) {
+ Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
+ final String childAsString = ((XSString) children.get(0)).getValue();
+ Assert.assertTrue(s1.equals(childAsString) || s2.equals(childAsString));
+ }
+ }
+
+ @Test public void multiDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(STRING_1 + DELIMITER + SCOPE_1);
+
+ final XSString stringValue2 = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue2.setValue(STRING_2 + DELIMITER + SCOPE_2);
+
+ final XSString stringValue3 = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue3.setValue(STRING_2 + "@" + SCOPE_2);
+
+ final XSString stringValue4 = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue4.setValue(STRING_2);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.getAttributeValues().add(stringValue);
+ samlAttribute.getAttributeValues().add(stringValue2);
+ samlAttribute.getAttributeValues().add(stringValue3);
+ samlAttribute.getAttributeValues().add(stringValue4);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 2);
+
+ final ScopedStringAttributeValue value1 = (ScopedStringAttributeValue) attr.getValues().get(0);
+ final ScopedStringAttributeValue value2 = (ScopedStringAttributeValue) attr.getValues().get(1);
+ Assert.assertTrue(STRING_1.equals(value1.getValue()) || STRING_1.equals(value2.getValue()));
+ Assert.assertTrue(STRING_2.equals(value1.getValue()) || STRING_2.equals(value2.getValue()));
+ Assert.assertTrue(SCOPE_1.equals(value1.getScope()) || SCOPE_1.equals(value2.getScope()));
+ Assert.assertTrue(SCOPE_2.equals(value1.getScope()) || SCOPE_2.equals(value2.getScope()));
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java
new file mode 100644
index 0000000..1182837
--- /dev/null
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java
@@ -0,0 +1,364 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.ByteAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
+import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+import org.opensaml.core.OpenSAMLInitBaseTestCase;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.XMLObjectBuilder;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeValue;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/** {@link SAML2StringAttributeTranscoder} unit test. */
+public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
+
+ private AttributeTranscoderRegistryImpl registry;
+
+ private XMLObjectBuilder<XSString> stringBuilder;
+
+ private SAMLObjectBuilder<Attribute> attributeBuilder;
+
+ private SAMLObjectBuilder<RequestedAttribute> reqAttributeBuilder;
+
+ private final static String ATTR_NAME = "foo";
+ private final static String ATTR_NAMEFORMAT = "Namespace";
+ private final static String ATTR_FRIENDLYNAME = "friendly";
+ private final static String STRING_1 = "Value The First";
+ private final static String STRING_2 = "Second string the value is";
+
+ @BeforeClass public void setUp() throws ComponentInitializationException {
+
+ stringBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
+
+ attributeBuilder = (SAMLObjectBuilder<Attribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
+ Attribute.TYPE_NAME);
+ reqAttributeBuilder = (SAMLObjectBuilder<RequestedAttribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<RequestedAttribute>getBuilderOrThrow(
+ RequestedAttribute.TYPE_NAME);
+
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ final SAML2StringAttributeTranscoder transcoder = new SAML2StringAttributeTranscoder();
+ transcoder.initialize();
+
+ registry.setNamingRegistry(Collections.singletonMap(transcoder.getEncodedType(),
+ new AbstractSAML2AttributeTranscoder.NamingFunction()));
+
+ final Map<String,Object> ruleset1 = new HashMap<>();
+ ruleset1.put(AttributeTranscoderRegistry.PROP_ID, ATTR_NAME);
+ ruleset1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_ENCODE_TYPE, true);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_NAME, ATTR_NAME);
+ ruleset1.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT, ATTR_NAMEFORMAT);
+ ruleset1.put(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME, ATTR_FRIENDLYNAME);
+
+ registry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(ruleset1)));
+
+ registry.initialize();
+ }
+
+ @AfterClass public void tearDown() {
+ registry.destroy();
+ registry = null;
+ }
+
+ @Test public void emptyEncode() throws Exception {
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+ Assert.assertTrue(attr.getAttributeValues().isEmpty());
+ }
+
+ @Test public void emptyDecode() throws Exception {
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test public void emptyRequestedDecode() throws Exception {
+
+ final RequestedAttribute samlAttribute = reqAttributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.setIsRequired(true);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
+ final int[] intArray = {1, 2, 3, 4};
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue<Object>() {
+ @Override
+ public Object getValue() {
+ return intArray;
+ }
+ @Override
+ public String getDisplayValue() {
+ return intArray.toString();
+ }
+ });
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void single() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+
+ final XMLObject child = children.get(0);
+
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+
+ Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
+
+ final XSString childAsString = (XSString) child;
+
+ Assert.assertEquals(childAsString.getValue(), STRING_1);
+ }
+
+ @Test public void singleRequested() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
+
+ final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
+ inputAttribute.setRequired(true);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final RequestedAttribute attr = TranscoderSupport.<RequestedAttribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, RequestedAttribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+ Assert.assertTrue(attr.isRequired());
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+
+ final XMLObject child = children.get(0);
+
+ Assert.assertEquals(child.getElementQName(), AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+
+ Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
+
+ final XSString childAsString = (XSString) child;
+
+ Assert.assertEquals(childAsString.getValue(), STRING_1);
+ }
+
+ @Test public void singleDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(STRING_1);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 1);
+ Assert.assertEquals(attr.getValues().get(0).getValue().toString(), STRING_1);
+ }
+
+
+ @Test public void singleRequestedDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(STRING_1);
+
+ final RequestedAttribute samlAttribute = reqAttributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.setIsRequired(true);
+ samlAttribute.getAttributeValues().add(stringValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertEquals(attr.getValues().size(), 1);
+ Assert.assertEquals(attr.getValues().get(0).getValue().toString(), STRING_1);
+ }
+
+ @Test public void multi() throws Exception {
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
+ new StringAttributeValue(STRING_1),
+ new StringAttributeValue(STRING_2),
+ new ScopedStringAttributeValue(STRING_1, STRING_2));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+ Assert.assertEquals(children.size(), 3, "Encoding three entries");
+
+ for (final XMLObject child: children) {
+ Assert.assertTrue(child instanceof XSString, "Child of result attribute should be a string");
+ final String childAsString = ((XSString) children.get(0)).getValue();
+ Assert.assertTrue(STRING_1.equals(childAsString)||STRING_2.equals(childAsString));
+ }
+ }
+
+ @Test public void multiDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue.setValue(STRING_1);
+
+ final XSString stringValue2 = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringValue2.setValue(STRING_2);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.getAttributeValues().add(stringValue);
+ samlAttribute.getAttributeValues().add(stringValue2);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 2);
+ Assert.assertEquals(attr.getValues().get(0).getValue().toString(), STRING_1);
+ Assert.assertEquals(attr.getValues().get(1).getValue().toString(), STRING_2);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java
new file mode 100644
index 0000000..92f1e2c
--- /dev/null
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java
@@ -0,0 +1,429 @@
+/*
+ * 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.idp.saml.attribute.transcoding.impl;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.ByteAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.IdPRequestedAttribute;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+import org.opensaml.core.OpenSAMLInitBaseTestCase;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.XMLObjectBuilder;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSAny;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeValue;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/** {@link SAML2XMLObjectAttributeTranscoder} unit test. */
+public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
+
+ private AttributeTranscoderRegistryImpl registry;
+
+ private XMLObjectBuilder<XSAny> anyBuilder;
+
+ private XMLObjectBuilder<XSString> stringBuilder;
+
+ private SAMLObjectBuilder<Attribute> attributeBuilder;
+
+ private SAMLObjectBuilder<RequestedAttribute> reqAttributeBuilder;
+
+ private final static String ATTR_NAME = "foo";
+ private final static String ATTR_NAMEFORMAT = "Namespace";
+ private final static String ATTR_FRIENDLYNAME = "friendly";
+ private final static String STRING_1 = "Value The First";
+ private final static String STRING_2 = "Second string the value is";
+
+ @BeforeClass public void setUp() throws ComponentInitializationException {
+
+ anyBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSAny>getBuilderOrThrow(XSAny.TYPE_NAME);
+ stringBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
+
+ attributeBuilder = (SAMLObjectBuilder<Attribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
+ Attribute.TYPE_NAME);
+ reqAttributeBuilder = (SAMLObjectBuilder<RequestedAttribute>)
+ XMLObjectProviderRegistrySupport.getBuilderFactory().<RequestedAttribute>getBuilderOrThrow(
+ RequestedAttribute.TYPE_NAME);
+
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ final SAML2XMLObjectAttributeTranscoder transcoder = new SAML2XMLObjectAttributeTranscoder();
+ transcoder.initialize();
+
+ registry.setNamingRegistry(Collections.singletonMap(transcoder.getEncodedType(),
+ new AbstractSAML2AttributeTranscoder.NamingFunction()));
+
+ final Map<String,Object> ruleset1 = new HashMap<>();
+ ruleset1.put(AttributeTranscoderRegistry.PROP_ID, ATTR_NAME);
+ ruleset1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_ENCODE_TYPE, true);
+ ruleset1.put(SAMLAttributeTranscoder.PROP_NAME, ATTR_NAME);
+ ruleset1.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT, ATTR_NAMEFORMAT);
+ ruleset1.put(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME, ATTR_FRIENDLYNAME);
+
+ registry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(ruleset1)));
+
+ registry.initialize();
+ }
+
+ @AfterClass public void tearDown() {
+ registry.destroy();
+ registry = null;
+ }
+
+ @Test public void emptyEncode() throws Exception {
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+ Assert.assertTrue(attr.getAttributeValues().isEmpty());
+ }
+
+ @Test public void emptyDecode() throws Exception {
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test public void emptyRequestedDecode() throws Exception {
+
+ final RequestedAttribute samlAttribute = reqAttributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.setIsRequired(true);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertTrue(attr.getValues().isEmpty());
+ }
+
+ @Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
+ final int[] intArray = {1, 2, 3, 4};
+ final Collection<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue<Object>() {
+ @Override
+ public Object getValue() {
+ return intArray;
+ }
+ @Override
+ public String getDisplayValue() {
+ return intArray.toString();
+ }
+ });
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
+ }
+
+ @Test public void single() throws Exception {
+ final List<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), objectFor(STRING_1));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+ Assert.assertEquals(children.get(0).getElementQName(),
+ AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ Assert.assertEquals(children.get(0).getOrderedChildren().size(), 1,
+ "Expected exactly one child inside the <AttributeValue/>");
+
+ checkValues(children.get(0).getOrderedChildren().get(0), STRING_1);
+ }
+
+ @Test public void singleRequested() throws Exception {
+ final List<IdPAttributeValue<?>> values =
+ Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), objectFor(STRING_1));
+
+ final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
+ inputAttribute.setRequired(true);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final RequestedAttribute attr = TranscoderSupport.<RequestedAttribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, RequestedAttribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getName(), ATTR_NAME);
+ Assert.assertEquals(attr.getNameFormat(), ATTR_NAMEFORMAT);
+ Assert.assertEquals(attr.getFriendlyName(), ATTR_FRIENDLYNAME);
+ Assert.assertTrue(attr.isRequired());
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+ Assert.assertEquals(children.size(), 1, "Encoding one entry");
+ Assert.assertEquals(children.get(0).getElementQName(),
+ AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ Assert.assertEquals(children.get(0).getOrderedChildren().size(), 1,
+ "Expected exactly one child inside the <AttributeValue/>");
+
+ checkValues(children.get(0).getOrderedChildren().get(0), STRING_1);
+ }
+
+ @Test public void singleDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(new QName("Foo"));
+ stringValue.setValue(STRING_1);
+
+ final XSAny attrValue = anyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ attrValue.getUnknownXMLObjects().add(stringValue);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.getAttributeValues().add(attrValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 1);
+
+ final XMLObjectAttributeValue value = (XMLObjectAttributeValue) attr.getValues().get(0);
+ Assert.assertTrue(value.getValue() instanceof XSString);
+ Assert.assertEquals(value.getValue().getElementQName().getLocalPart(), "Foo");
+ Assert.assertEquals(((XSString) value.getValue()).getValue(), STRING_1);
+ }
+
+
+ @Test public void singleRequestedDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(new QName("Foo"));
+ stringValue.setValue(STRING_1);
+
+ final XSAny attrValue = anyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ attrValue.getUnknownXMLObjects().add(stringValue);
+
+ final RequestedAttribute samlAttribute = reqAttributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.setIsRequired(true);
+ samlAttribute.getAttributeValues().add(attrValue);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertTrue(attr instanceof IdPRequestedAttribute);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertTrue(((IdPRequestedAttribute) attr).getIsRequired());
+ Assert.assertEquals(attr.getValues().size(), 1);
+
+ final XMLObjectAttributeValue value = (XMLObjectAttributeValue) attr.getValues().get(0);
+ Assert.assertTrue(value.getValue() instanceof XSString);
+ Assert.assertEquals(((XSString) value.getValue()).getValue(), STRING_1);
+ }
+
+ @Test public void multi() throws Exception {
+ final List<IdPAttributeValue<?>> values =
+ Arrays.asList(objectFor(STRING_1), objectFor(STRING_2));
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(values);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
+ null, inputAttribute, Attribute.class, ruleset);
+
+ Assert.assertNotNull(attr);
+
+ final List<XMLObject> children = attr.getOrderedChildren();
+ Assert.assertEquals(children.size(), 2, "Encoding two entries");
+
+ Assert.assertEquals(children.get(0).getElementQName(),
+ AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ Assert.assertEquals(children.get(0).getOrderedChildren().size(), 1,
+ "Expected exactly one child inside the <AttributeValue/> for first Attribute");
+
+ Assert.assertEquals(children.get(1).getElementQName(),
+ AttributeValue.DEFAULT_ELEMENT_NAME,
+ "Attribute Value not inside <AttributeValue/>");
+ Assert.assertEquals(children.get(1).getOrderedChildren().size(), 1,
+ "Expected exactly one child inside the <AttributeValue/> for second Attribute");
+
+ checkValues(children.get(0).getOrderedChildren().get(0), STRING_1, STRING_2);
+ checkValues(children.get(1).getOrderedChildren().get(0), STRING_1, STRING_2);
+ }
+
+ @Test public void multiDecode() throws Exception {
+
+ final XSString stringValue = stringBuilder.buildObject(new QName("Foo"));
+ stringValue.setValue(STRING_1);
+
+ final XSAny attrValue = anyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ attrValue.getUnknownXMLObjects().add(stringValue);
+
+ final XSString stringValue2 = stringBuilder.buildObject(new QName("Bar"));
+ stringValue2.setValue(STRING_2);
+
+ final XSAny attrValue2 = anyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ attrValue2.getUnknownXMLObjects().add(stringValue2);
+
+ final Attribute samlAttribute = attributeBuilder.buildObject();
+ samlAttribute.setName(ATTR_NAME);
+ samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
+ samlAttribute.getAttributeValues().add(attrValue);
+ samlAttribute.getAttributeValues().add(attrValue2);
+
+ final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
+ Assert.assertEquals(rulesets.size(), 1);
+ final TranscodingRule ruleset = rulesets.iterator().next();
+
+ final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
+
+ Assert.assertNotNull(attr);
+ Assert.assertEquals(attr.getId(), ATTR_NAME);
+ Assert.assertEquals(attr.getValues().size(), 2);
+
+ final XMLObjectAttributeValue value = (XMLObjectAttributeValue) attr.getValues().get(0);
+ Assert.assertTrue(value.getValue() instanceof XSString);
+
+ final XMLObjectAttributeValue value2 = (XMLObjectAttributeValue) attr.getValues().get(1);
+ Assert.assertTrue(value2.getValue() instanceof XSString);
+
+ final String s1 = ((XSString) value.getValue()).getValue();
+ final String s2 = ((XSString) value2.getValue()).getValue();
+
+ Assert.assertTrue(STRING_1.equals(s1) || STRING_2.equals(s1));
+ Assert.assertTrue(STRING_1.equals(s2) || STRING_2.equals(s2));
+ }
+
+ /**
+ * Create an XML object from a string which we can test against later.
+ *
+ * @param value that we encode
+ * @return an XML object
+ */
+ private static XMLObjectAttributeValue objectFor(final String value) {
+
+ final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
+ inputAttribute.setValues(Collections.singletonList(new StringAttributeValue(value)));
+ return new XMLObjectAttributeValue(
+ SAMLEncoderSupport.encodeStringValue(inputAttribute, new QName("Foo"), value, true));
+ }
+
+ /**
+ * Check that the input XML object is what was expected.
+ *
+ * @param input the objects in question.
+ * @param possibles the strings that they might be encoding.
+ */
+ private static void checkValues(final XMLObject input, final String... possibles) {
+
+ Assert.assertTrue(input instanceof XSString);
+ final String s = ((XSString) input).getValue();
+
+ for (String possible : possibles) {
+ if (s.equals(possible)) {
+ return;
+ }
+ }
+ Assert.assertTrue(false, "No potential match");
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertionTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertionTest.java
index c7685f8..a0a4660 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertionTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertionTest.java
@@ -18,8 +18,9 @@
package net.shibboleth.idp.saml.saml1.profile.impl;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -28,14 +29,22 @@ import net.shibboleth.idp.attribute.AttributeEncodingException;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.StringAttributeValue;
import net.shibboleth.idp.attribute.context.AttributeContext;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
import net.shibboleth.idp.profile.ActionTestingSupport;
import net.shibboleth.idp.profile.IdPEventIds;
import net.shibboleth.idp.profile.RequestContextBuilder;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML1StringAttributeEncoder;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1StringAttributeTranscoder;
import net.shibboleth.idp.saml.saml1.profile.SAML1ActionTestingSupport;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.service.AbstractReloadableService;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
import org.opensaml.core.OpenSAMLInitBaseTestCase;
import org.opensaml.core.xml.XMLObject;
@@ -44,6 +53,7 @@ import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.saml.saml1.core.Assertion;
import org.opensaml.saml.saml1.core.Attribute;
+import org.opensaml.saml.saml1.core.AttributeDesignator;
import org.opensaml.saml.saml1.core.AttributeStatement;
import org.opensaml.saml.saml1.core.Response;
import org.springframework.webflow.execution.Event;
@@ -79,12 +89,49 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
private AddAttributeStatementToAssertion action;
+ private AttributeTranscoderRegistryImpl registry;
+
@BeforeMethod public void setUp() throws ComponentInitializationException {
rc = new RequestContextBuilder().setOutboundMessage(
SAML1ActionTestingSupport.buildResponse()).buildRequestContext();
prc = new WebflowRequestContextProfileRequestContextLookup().apply(rc);
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ registry.setNamingRegistry(Collections.singletonMap(AttributeDesignator.class,
+ new AbstractSAML1AttributeTranscoder.NamingFunction()));
+
+ final SAML1StringAttributeTranscoder transcoder = new SAML1StringAttributeTranscoder();
+ transcoder.initialize();
+
+ final Map<String,Object> rule1_1 = new HashMap<>();
+ rule1_1.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_1);
+ rule1_1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule1_1.put(SAMLAttributeTranscoder.PROP_NAME, MY_NAME_1);
+ rule1_1.put(SAML1AttributeTranscoder.PROP_NAMESPACE, MY_NAMESPACE);
+
+ final Map<String,Object> rule1_2 = new HashMap<>();
+ rule1_2.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_1);
+ rule1_2.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule1_2.put(SAMLAttributeTranscoder.PROP_NAME, MY_ALTNAME_1);
+ rule1_2.put(SAML1AttributeTranscoder.PROP_NAMESPACE, MY_NAMESPACE);
+
+ final Map<String,Object> rule2_1 = new HashMap<>();
+ rule2_1.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_2);
+ rule2_1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule2_1.put(SAMLAttributeTranscoder.PROP_NAME, MY_NAME_2);
+ rule2_1.put(SAML1AttributeTranscoder.PROP_NAMESPACE, MY_NAMESPACE);
+
+ registry.setTranscoderRegistry(Arrays.asList(
+ new TranscodingRule(rule1_1),
+ new TranscodingRule(rule1_2),
+ new TranscodingRule(rule2_1)));
+
+ registry.initialize();
+
action = new AddAttributeStatementToAssertion();
+ action.setTranscoderRegistry(new RegistryService(registry));
}
/** Test that the action errors out properly if there is no relying party context. */
@@ -127,14 +174,30 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
/** Test that the action ignores attribute encoding errors. */
@Test public void testIgnoreAttributeEncodingErrors() throws Exception {
- final MockSAML1StringAttributeEncoder attributeEncoder = new MockSAML1StringAttributeEncoder();
+
+ final AttributeTranscoderRegistryImpl localregistry = new AttributeTranscoderRegistryImpl();
+ localregistry.setId("test");
+
+ localregistry.setNamingRegistry(Collections.singletonMap(AttributeDesignator.class,
+ new AbstractSAML1AttributeTranscoder.NamingFunction()));
+
+ final MockSAML1StringAttributeTranscoder transcoder = new MockSAML1StringAttributeTranscoder();
+ transcoder.initialize();
+
+ final Map<String,Object> rule = new HashMap<>();
+ rule.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_1);
+ rule.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule.put(SAMLAttributeTranscoder.PROP_NAME, MY_NAME_1);
+ rule.put(SAML1AttributeTranscoder.PROP_NAMESPACE, MY_NAMESPACE);
+
+ localregistry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(rule)));
+ localregistry.initialize();
+
+ action.setTranscoderRegistry(new RegistryService(localregistry));
final IdPAttribute attribute = new IdPAttribute(MY_NAME_1);
attribute.setValues(Arrays.asList(new StringAttributeValue(MY_VALUE_1)));
- final Collection collection = Arrays.asList(attributeEncoder);
- attribute.setEncoders(collection);
-
final AttributeContext attribCtx = new AttributeContext();
attribCtx.setIdPAttributes(Arrays.asList(attribute));
prc.getSubcontext(RelyingPartyContext.class).addSubcontext(attribCtx);
@@ -147,14 +210,30 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
/** Test that the action returns the correct transition when an attribute encoding error occurs. */
@Test public void failOnAttributeEncodingErrors() throws Exception {
- final MockSAML1StringAttributeEncoder attributeEncoder = new MockSAML1StringAttributeEncoder();
+
+ final AttributeTranscoderRegistryImpl localregistry = new AttributeTranscoderRegistryImpl();
+ localregistry.setId("test");
+
+ localregistry.setNamingRegistry(Collections.singletonMap(AttributeDesignator.class,
+ new AbstractSAML1AttributeTranscoder.NamingFunction()));
+
+ final MockSAML1StringAttributeTranscoder transcoder = new MockSAML1StringAttributeTranscoder();
+ transcoder.initialize();
+
+ final Map<String,Object> rule = new HashMap<>();
+ rule.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_1);
+ rule.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule.put(SAMLAttributeTranscoder.PROP_NAME, MY_NAME_1);
+ rule.put(SAML1AttributeTranscoder.PROP_NAMESPACE, MY_NAMESPACE);
+
+ localregistry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(rule)));
+ localregistry.initialize();
+
+ action.setTranscoderRegistry(new RegistryService(localregistry));
final IdPAttribute attribute = new IdPAttribute(MY_NAME_1);
attribute.setValues(Arrays.asList(new StringAttributeValue(MY_VALUE_1)));
- final Collection collection = Arrays.asList(attributeEncoder);
- attribute.setEncoders(collection);
-
final AttributeContext attribCtx = new AttributeContext();
attribCtx.setIdPAttributes(Arrays.asList(attribute));
prc.getSubcontext(RelyingPartyContext.class).addSubcontext(attribCtx);
@@ -254,30 +333,9 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
final IdPAttribute attribute1 = new IdPAttribute(MY_NAME_1);
attribute1.setValues(Arrays.asList(new StringAttributeValue(MY_VALUE_1)));
- final SAML1StringAttributeEncoder attributeEncoder1 = new SAML1StringAttributeEncoder();
- attributeEncoder1.setName(MY_NAME_1);
- attributeEncoder1.setNamespace(MY_NAMESPACE);
- attributeEncoder1.initialize();
-
- final SAML1StringAttributeEncoder attributeEncoder1_2 = new SAML1StringAttributeEncoder();
- attributeEncoder1_2.setName(MY_ALTNAME_1);
- attributeEncoder1_2.setNamespace(MY_NAMESPACE);
- attributeEncoder1_2.initialize();
-
- final Collection collection1 = Arrays.asList(attributeEncoder1, attributeEncoder1_2);
- attribute1.setEncoders(collection1);
-
final IdPAttribute attribute2 = new IdPAttribute(MY_NAME_2);
attribute2.setValues(Collections.singletonList(new StringAttributeValue(MY_VALUE_2)));
- final SAML1StringAttributeEncoder attributeEncoder2 = new SAML1StringAttributeEncoder();
- attributeEncoder2.setName(MY_NAME_2);
- attributeEncoder2.setNamespace(MY_NAMESPACE);
- attributeEncoder2.initialize();
-
- final Collection collection2 = Arrays.asList(attributeEncoder2);
- attribute2.setEncoders(collection2);
-
final AttributeContext attribCtx = new AttributeContext();
attribCtx.setIdPAttributes(Arrays.asList(attribute1, attribute2));
@@ -321,12 +379,40 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
}
/** A mock SAML1 string attribute encoder which always throws an {@link AttributeEncodingException}. */
- private class MockSAML1StringAttributeEncoder extends SAML1StringAttributeEncoder {
+ private class MockSAML1StringAttributeTranscoder extends SAML1StringAttributeTranscoder {
/** {@inheritDoc} */
- @Nullable public Attribute encode(@Nonnull final IdPAttribute attribute) throws AttributeEncodingException {
+ @Override
+ @Nullable public Attribute encode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends AttributeDesignator> to,
+ @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
throw new AttributeEncodingException("Always thrown.");
}
}
+ private static class RegistryService extends AbstractReloadableService<AttributeTranscoderRegistry> {
+
+ private ServiceableComponent<AttributeTranscoderRegistry> component;
+
+ protected RegistryService(ServiceableComponent<AttributeTranscoderRegistry> what) {
+ component = what;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable public ServiceableComponent<AttributeTranscoderRegistry> getServiceableComponent() {
+ if (null == component) {
+ return null;
+ }
+ component.pinComponent();
+ return component;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean shouldReload() {
+ return false;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignatorsTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignatorsTest.java
index 9c56761..4d6bbb0 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignatorsTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignatorsTest.java
@@ -22,11 +22,12 @@ import static org.testng.Assert.assertEquals;
import java.util.Collection;
import java.util.List;
+import javax.annotation.Nullable;
+
import org.opensaml.core.xml.XMLObjectBaseTestCase;
import org.opensaml.core.xml.io.UnmarshallingException;
import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.saml.saml1.core.AttributeDesignator;
-import org.opensaml.saml.saml1.core.AttributeQuery;
+import org.opensaml.saml.saml1.core.Request;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.webflow.execution.Event;
@@ -41,13 +42,16 @@ import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
import net.shibboleth.idp.attribute.StringAttributeValue;
import net.shibboleth.idp.attribute.context.AttributeContext;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
import net.shibboleth.idp.profile.ActionTestingSupport;
import net.shibboleth.idp.profile.RequestContextBuilder;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.SAML1AttributeDesignatorsMapper;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.service.AbstractReloadableService;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
import net.shibboleth.utilities.java.support.xml.XMLParserException;
/** Tests for {@link FilterByQueriedAttributeDesignators} */
@@ -55,9 +59,9 @@ public class FilterByQueriedAttributeDesignatorsTest extends XMLObjectBaseTestCa
static final String PATH = "/net/shibboleth/idp/saml/impl/profile/";
- private AttributeQuery query;
+ private Request query;
- private AttributesMapper<AttributeDesignator, IdPAttribute> mapper;
+ private ReloadableService<AttributeTranscoderRegistry> registry;
private FilterByQueriedAttributeDesignators action;
@@ -86,16 +90,19 @@ public class FilterByQueriedAttributeDesignatorsTest extends XMLObjectBaseTestCa
}
}
- @BeforeClass public void setup() throws XMLParserException, UnmarshallingException {
- query = unmarshallElement(PATH + "AttributeQuerySaml1.xml", true);
- mapper = getBean(PATH + "saml1Mapper.xml", SAML1AttributeDesignatorsMapper.class);
+ @BeforeClass public void setup() {
+ registry = new RegistryService(getBean(PATH + "saml1Mapper.xml", AttributeTranscoderRegistryImpl.class));
}
- @BeforeMethod public void setUpMethod() throws ComponentInitializationException {
- action = new FilterByQueriedAttributeDesignators(mapper);
+ @BeforeMethod public void setUpMethod() throws ComponentInitializationException, XMLParserException, UnmarshallingException {
+ query = unmarshallElement(PATH + "AttributeQuerySaml1.xml", true);
+
+ action = new FilterByQueriedAttributeDesignators();
+ action.setTranscoderRegistry(registry);
+ action.initialize();
+
rc = new RequestContextBuilder().setInboundMessage(query).buildRequestContext();
prc = new WebflowRequestContextProfileRequestContextLookup().apply(rc);
- action.initialize();
}
@Test public void noAttributes() {
@@ -107,13 +114,18 @@ public class FilterByQueriedAttributeDesignatorsTest extends XMLObjectBaseTestCa
@Test public void noValues() {
final RelyingPartyContext rpc = prc.getSubcontext(RelyingPartyContext.class,true);
final AttributeContext ac = rpc.getSubcontext(AttributeContext.class,true);
- final List<IdPAttribute> attributes = List.of(new IdPAttribute("eduPersonAssurance"), new IdPAttribute("flooby"), new IdPAttribute("eduPersonScopedAffiliation"), new IdPAttribute("eduPersonTargetedID"));
+ final List<IdPAttribute> attributes = List.of(
+ new IdPAttribute("eduPersonAssurance"),
+ new IdPAttribute("flooby"),
+ new IdPAttribute("eduPersonScopedAffiliation"),
+ new IdPAttribute("eduPersonTargetedID"));
ac.setIdPAttributes(attributes);
final Event event = action.execute(rc);
ActionTestingSupport.assertProceedEvent(event);
- assertEquals(ac.getIdPAttributes().size(), 4);
+ assertEquals(ac.getIdPAttributes().size(), 3);
}
-
+
+ /** This is a non-issue for SAML 1, but just for completeness. */
@Test public void values() {
final RelyingPartyContext rpc = prc.getSubcontext(RelyingPartyContext.class,true);
final AttributeContext ac = rpc.getSubcontext(AttributeContext.class,true);
@@ -128,7 +140,32 @@ public class FilterByQueriedAttributeDesignatorsTest extends XMLObjectBaseTestCa
ac.setIdPAttributes(attributes);
final Event event = action.execute(rc);
ActionTestingSupport.assertProceedEvent(event);
- assertEquals(ac.getIdPAttributes().size(), 4);
+ assertEquals(ac.getIdPAttributes().size(), 3);
+ }
+
+ private static class RegistryService extends AbstractReloadableService<AttributeTranscoderRegistry> {
+
+ private ServiceableComponent<AttributeTranscoderRegistry> component;
+
+ protected RegistryService(ServiceableComponent<AttributeTranscoderRegistry> what) {
+ component = what;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable public ServiceableComponent<AttributeTranscoderRegistry> getServiceableComponent() {
+ if (null == component) {
+ return null;
+ }
+ component.pinComponent();
+ return component;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean shouldReload() {
+ return false;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertionTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertionTest.java
index 6279116..762877a 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertionTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertionTest.java
@@ -18,8 +18,9 @@
package net.shibboleth.idp.saml.saml2.profile.impl;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -28,14 +29,22 @@ import net.shibboleth.idp.attribute.AttributeEncodingException;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.StringAttributeValue;
import net.shibboleth.idp.attribute.context.AttributeContext;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
import net.shibboleth.idp.profile.ActionTestingSupport;
import net.shibboleth.idp.profile.IdPEventIds;
import net.shibboleth.idp.profile.RequestContextBuilder;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
-import net.shibboleth.idp.saml.attribute.encoding.impl.SAML2StringAttributeEncoder;
+import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
+import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2StringAttributeTranscoder;
import net.shibboleth.idp.saml.saml2.profile.SAML2ActionTestingSupport;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.service.AbstractReloadableService;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
import org.opensaml.core.OpenSAMLInitBaseTestCase;
import org.opensaml.core.xml.XMLObject;
@@ -79,12 +88,48 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
private AddAttributeStatementToAssertion action;
+ private AttributeTranscoderRegistryImpl registry;
+
@BeforeMethod public void setUp() throws ComponentInitializationException {
rc = new RequestContextBuilder().setOutboundMessage(
SAML2ActionTestingSupport.buildResponse()).buildRequestContext();
prc = new WebflowRequestContextProfileRequestContextLookup().apply(rc);
+ registry = new AttributeTranscoderRegistryImpl();
+ registry.setId("test");
+
+ registry.setNamingRegistry(Collections.singletonMap(Attribute.class,
+ new AbstractSAML2AttributeTranscoder.NamingFunction()));
+
+ final SAML2StringAttributeTranscoder transcoder = new SAML2StringAttributeTranscoder();
+ transcoder.initialize();
+
+ final Map<String,Object> rule1_1 = new HashMap<>();
+ rule1_1.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_1);
+ rule1_1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule1_1.put(SAMLAttributeTranscoder.PROP_NAME, MY_NAME_1);
+ rule1_1.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT, MY_NAMESPACE);
+
+ final Map<String,Object> rule1_2 = new HashMap<>();
+ rule1_2.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_1);
+ rule1_2.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule1_2.put(SAMLAttributeTranscoder.PROP_NAME, MY_ALTNAME_1);
+ rule1_2.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT, MY_NAMESPACE);
+
+ final Map<String,Object> rule2_1 = new HashMap<>();
+ rule2_1.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_2);
+ rule2_1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule2_1.put(SAMLAttributeTranscoder.PROP_NAME, MY_NAME_2);
+ rule2_1.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT, MY_NAMESPACE);
+
+ registry.setTranscoderRegistry(Arrays.asList(
+ new TranscodingRule(rule1_1),
+ new TranscodingRule(rule1_2),
+ new TranscodingRule(rule2_1)));
+ registry.initialize();
+
action = new AddAttributeStatementToAssertion();
+ action.setTranscoderRegistry(new RegistryService(registry));
}
/** Test that the action errors out properly if there is no relying party context. */
@@ -127,14 +172,30 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
/** Test that the action ignores attribute encoding errors. */
@Test public void testIgnoreAttributeEncodingErrors() throws Exception {
- final MockSAML2StringAttributeEncoder attributeEncoder = new MockSAML2StringAttributeEncoder();
+
+ final AttributeTranscoderRegistryImpl localregistry = new AttributeTranscoderRegistryImpl();
+ localregistry.setId("test");
+
+ localregistry.setNamingRegistry(Collections.singletonMap(Attribute.class,
+ new AbstractSAML2AttributeTranscoder.NamingFunction()));
+
+ final MockSAML2StringAttributeTranscoder transcoder = new MockSAML2StringAttributeTranscoder();
+ transcoder.initialize();
+
+ final Map<String,Object> rule = new HashMap<>();
+ rule.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_1);
+ rule.put(SAMLAttributeTranscoder.PROP_NAME, MY_NAME_1);
+ rule.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT, MY_NAMESPACE);
+
+ localregistry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(rule)));
+ localregistry.initialize();
+
+ action.setTranscoderRegistry(new RegistryService(localregistry));
final IdPAttribute attribute = new IdPAttribute(MY_NAME_1);
attribute.setValues(Arrays.asList(new StringAttributeValue(MY_VALUE_1)));
- final Collection collection = Arrays.asList(attributeEncoder);
- attribute.setEncoders(collection);
-
final AttributeContext attribCtx = new AttributeContext();
attribCtx.setIdPAttributes(Arrays.asList(attribute));
((RelyingPartyContext) prc.getSubcontext(RelyingPartyContext.class)).addSubcontext(attribCtx);
@@ -147,14 +208,30 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
/** Test that the action returns the correct transition when an attribute encoding error occurs. */
@Test public void failOnAttributeEncodingErrors() throws Exception {
- final MockSAML2StringAttributeEncoder attributeEncoder = new MockSAML2StringAttributeEncoder();
+
+ final AttributeTranscoderRegistryImpl localregistry = new AttributeTranscoderRegistryImpl();
+ localregistry.setId("test");
+
+ localregistry.setNamingRegistry(Collections.singletonMap(Attribute.class,
+ new AbstractSAML2AttributeTranscoder.NamingFunction()));
+
+ final MockSAML2StringAttributeTranscoder transcoder = new MockSAML2StringAttributeTranscoder();
+ transcoder.initialize();
+
+ final Map<String,Object> rule = new HashMap<>();
+ rule.put(AttributeTranscoderRegistry.PROP_ID, MY_NAME_1);
+ rule.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+ rule.put(SAMLAttributeTranscoder.PROP_NAME, MY_NAME_1);
+ rule.put(SAML2AttributeTranscoder.PROP_NAME_FORMAT, MY_NAMESPACE);
+
+ localregistry.setTranscoderRegistry(Collections.singletonList(new TranscodingRule(rule)));
+ localregistry.initialize();
+
+ action.setTranscoderRegistry(new RegistryService(localregistry));
final IdPAttribute attribute = new IdPAttribute(MY_NAME_1);
attribute.setValues(Arrays.asList(new StringAttributeValue(MY_VALUE_1)));
- final Collection collection = Arrays.asList(attributeEncoder);
- attribute.setEncoders(collection);
-
final AttributeContext attribCtx = new AttributeContext();
attribCtx.setIdPAttributes(Arrays.asList(attribute));
((RelyingPartyContext) prc.getSubcontext(RelyingPartyContext.class)).addSubcontext(attribCtx);
@@ -254,30 +331,9 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
final IdPAttribute attribute1 = new IdPAttribute(MY_NAME_1);
attribute1.setValues(Arrays.asList(new StringAttributeValue(MY_VALUE_1)));
- final SAML2StringAttributeEncoder attributeEncoder1 = new SAML2StringAttributeEncoder();
- attributeEncoder1.setName(MY_NAME_1);
- attributeEncoder1.setNameFormat(MY_NAMESPACE);
- attributeEncoder1.initialize();
-
- final SAML2StringAttributeEncoder attributeEncoder1_2 = new SAML2StringAttributeEncoder();
- attributeEncoder1_2.setName(MY_ALTNAME_1);
- attributeEncoder1_2.setNameFormat(MY_NAMESPACE);
- attributeEncoder1_2.initialize();
-
- final Collection collection1 = Arrays.asList(attributeEncoder1, attributeEncoder1_2);
- attribute1.setEncoders(collection1);
-
final IdPAttribute attribute2 = new IdPAttribute(MY_NAME_2);
attribute2.setValues(Collections.singletonList(new StringAttributeValue(MY_VALUE_2)));
- final SAML2StringAttributeEncoder attributeEncoder2 = new SAML2StringAttributeEncoder();
- attributeEncoder2.setName(MY_NAME_2);
- attributeEncoder2.setNameFormat(MY_NAMESPACE);
- attributeEncoder2.initialize();
-
- final Collection collection2 = Arrays.asList(attributeEncoder2);
- attribute2.setEncoders(collection2);
-
final AttributeContext attribCtx = new AttributeContext();
attribCtx.setIdPAttributes(Arrays.asList(attribute1, attribute2));
@@ -321,13 +377,41 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
}
}
- /** A mock SAML2 string attribute encoder which always throws an {@link AttributeEncodingException}. */
- private class MockSAML2StringAttributeEncoder extends SAML2StringAttributeEncoder {
+ /** A mock SAML2 string attribute transcoder which always throws an {@link AttributeEncodingException}. */
+ private class MockSAML2StringAttributeTranscoder extends SAML2StringAttributeTranscoder {
/** {@inheritDoc} */
- @Nullable public Attribute encode(@Nonnull final IdPAttribute attribute) throws AttributeEncodingException {
+ @Override
+ @Nullable public Attribute encode(@Nullable final ProfileRequestContext profileRequestContext,
+ @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends Attribute> to,
+ @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
throw new AttributeEncodingException("Always thrown.");
}
}
+ private static class RegistryService extends AbstractReloadableService<AttributeTranscoderRegistry> {
+
+ private ServiceableComponent<AttributeTranscoderRegistry> component;
+
+ protected RegistryService(ServiceableComponent<AttributeTranscoderRegistry> what) {
+ component = what;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable public ServiceableComponent<AttributeTranscoderRegistry> getServiceableComponent() {
+ if (null == component) {
+ return null;
+ }
+ component.pinComponent();
+ return component;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean shouldReload() {
+ return false;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributesTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributesTest.java
index 4c6d0c5..cc6738c 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributesTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributesTest.java
@@ -22,10 +22,11 @@ import static org.testng.Assert.assertEquals;
import java.util.Collection;
import java.util.List;
+import javax.annotation.Nullable;
+
import org.opensaml.core.xml.XMLObjectBaseTestCase;
import org.opensaml.core.xml.io.UnmarshallingException;
import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.saml.saml2.core.Attribute;
import org.opensaml.saml.saml2.core.AttributeQuery;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
@@ -41,13 +42,16 @@ import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
import net.shibboleth.idp.attribute.StringAttributeValue;
import net.shibboleth.idp.attribute.context.AttributeContext;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
import net.shibboleth.idp.profile.ActionTestingSupport;
import net.shibboleth.idp.profile.RequestContextBuilder;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
-import net.shibboleth.idp.saml.attribute.mapping.AttributesMapper;
-import net.shibboleth.idp.saml.attribute.mapping.impl.SAML2AttributesMapper;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.service.AbstractReloadableService;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
import net.shibboleth.utilities.java.support.xml.XMLParserException;
/** Tests for {@link FilterByQueriedAttributes} */
@@ -57,7 +61,7 @@ public class FilterByQueriedAttributesTest extends XMLObjectBaseTestCase {
private AttributeQuery query;
- private AttributesMapper<Attribute, IdPAttribute> mapper;
+ private ReloadableService<AttributeTranscoderRegistry> registry;
private FilterByQueriedAttributes action;
@@ -86,16 +90,18 @@ public class FilterByQueriedAttributesTest extends XMLObjectBaseTestCase {
}
}
- @BeforeClass public void setup() throws XMLParserException, UnmarshallingException {
- query = unmarshallElement(PATH + "AttributeQuery.xml", true);
- mapper = getBean(PATH + "saml2Mapper.xml", SAML2AttributesMapper.class);
+ @BeforeClass public void setup() {
+ registry = new RegistryService(getBean(PATH + "saml2Mapper.xml", AttributeTranscoderRegistryImpl.class));
}
- @BeforeMethod public void setUpMethod() throws ComponentInitializationException {
- action = new FilterByQueriedAttributes(mapper);
+ @BeforeMethod public void setUpMethod() throws ComponentInitializationException, XMLParserException, UnmarshallingException {
+ query = unmarshallElement(PATH + "AttributeQuery.xml", true);
+ action = new FilterByQueriedAttributes();
+ action.setTranscoderRegistry(registry);
+ action.initialize();
+
rc = new RequestContextBuilder().setInboundMessage(query).buildRequestContext();
prc = new WebflowRequestContextProfileRequestContextLookup().apply(rc);
- action.initialize();
}
@Test public void noAttributes() {
@@ -107,7 +113,11 @@ public class FilterByQueriedAttributesTest extends XMLObjectBaseTestCase {
@Test public void noValues() {
final RelyingPartyContext rpc = prc.getSubcontext(RelyingPartyContext.class,true);
final AttributeContext ac = rpc.getSubcontext(AttributeContext.class,true);
- final List<IdPAttribute> attributes = List.of(new IdPAttribute("eduPersonAssurance"), new IdPAttribute("flooby"), new IdPAttribute("eduPersonScopedAffiliation"), new IdPAttribute("eduPersonTargetedID"));
+ final List<IdPAttribute> attributes = List.of(
+ new IdPAttribute("eduPersonAssurance"),
+ new IdPAttribute("flooby"),
+ new IdPAttribute("eduPersonScopedAffiliation"),
+ new IdPAttribute("eduPersonTargetedID"));
ac.setIdPAttributes(attributes);
final Event event = action.execute(rc);
ActionTestingSupport.assertProceedEvent(event);
@@ -131,4 +141,29 @@ public class FilterByQueriedAttributesTest extends XMLObjectBaseTestCase {
assertEquals(ac.getIdPAttributes().size(), 2);
}
-}
+ private static class RegistryService extends AbstractReloadableService<AttributeTranscoderRegistry> {
+
+ private ServiceableComponent<AttributeTranscoderRegistry> component;
+
+ protected RegistryService(ServiceableComponent<AttributeTranscoderRegistry> what) {
+ component = what;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable public ServiceableComponent<AttributeTranscoderRegistry> getServiceableComponent() {
+ if (null == component) {
+ return null;
+ }
+ component.pinComponent();
+ return component;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean shouldReload() {
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/attribute/mapping/attributesMapper.xml b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/attribute/mapping/attributesMapper.xml
deleted file mode 100644
index a079a3d..0000000
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/attribute/mapping/attributesMapper.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
- <!-- This is what we are trying to reverse map (note bi-directional aliasing, just to confuse things. And me.
-
- <AttributeDefinition xsi:type="ad:Simple" id="eduPersonAssurance" >
- <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAssurance" />
- <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" friendlyName="eduPersonAssurance" />
- <AttributeEncoder xsi:type="SAML2String" nameFormat="http://example.org/Format" name="http://example.org/name/for/Attribute" friendlyName="otherSAMLName" />
- </AttributeDefinition>
-
- <AttributeDefinition xsi:type="ad:Simple" id="otherPersonAssurance" >
- <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAssurance" />
- <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" friendlyName="eduPersonAssurance" />
- </AttributeDefinition>
-
- <AttributeDefinition xsi:type="ad:Scoped" id="eduPersonScopedAffiliation" scope="example.org" >
- <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" />
- <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" friendlyName="eduPersonScopedAffiliation"
- scopeDelimiter='#'/>
- </AttributeDefinition>
-
- <AttributeDefinition xsi:type="ad:SAML2NameID" id="eduPersonTargetedID"
- nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
- <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" />
- <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="eduPersonTargetedID" />
- </AttributeDefinition>
-
-
- But note that this is unmappable (no source name)
-
- <AttributeDefinition id="transientId" xsi:type="ad:TransientId">
- <AttributeEncoder xsi:type="SAML1StringNameIdentifier" nameFormat="urn:mace:shibboleth:1.0:nameIdentifier"/>
- <AttributeEncoder xsi:type="SAML2StringNameID" nameFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
- </AttributeDefinition>
-
-
- -->
-
- <bean id="abstractStringMapper" init-method="initialize" abstract="true"
- class="net.shibboleth.idp.saml.attribute.mapping.impl.RequestedAttributeMapper">
- <property name="valueMapper">
- <bean
- class="net.shibboleth.idp.saml.attribute.mapping.impl.StringAttributeValueMapper" />
- </property>
- </bean>
-
- <bean id="RequestedAttributesMapper"
- class="net.shibboleth.idp.saml.attribute.mapping.impl.RequestedAttributesMapper"
- init-method="initialize" p:id="RequestedAttributesMapper">
- <property name="mappers">
- <list>
- <bean parent="abstractStringMapper">
- <property name="id" value="eduPersonAssurance" />
- <property name="SAMLName" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" />
- <property name="attributeIds">
- <list>
- <value>eduPersonAssurance</value>
- <value>otherPersonAssurance</value>
- </list>
- </property>
- </bean>
- <bean parent="abstractStringMapper">
- <property name="SAMLName" value="http://example.org/name/for/Attribute" />
- <property name="id" value="otherSAMLName" />
- <property name="attributeFormat" value="http://example.org/Format " />
- <property name="attributeIds">
- <list>
- <value>eduPersonAssurance</value>
- </list>
- </property>
- </bean>
- <bean parent="abstractStringMapper">
- <property name="sAMLName" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" />
- <property name="id" value="eduPersonScopedAffiliation" />
- <property name="attributeFormat" value=" format " />
- <property name="valueMapper">
- <bean
- class="net.shibboleth.idp.saml.attribute.mapping.impl.ScopedStringAttributeValueMapper"
- p:delimiter="#" />
- </property>
- <property name="attributeIds">
- <list>
- <value>eduPersonScopedAffiliation</value>
- </list>
- </property>
- </bean>
- <bean parent="abstractStringMapper">
- <property name="attributeFormat" value="format"/>
- <property name="sAMLName" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
- <property name="id" value="eduPersonTargetedID"/>
- <property name="valueMapper">
- <bean
- class="net.shibboleth.idp.saml.attribute.mapping.impl.XMLObjectAttributeValueMapper" />
- </property>
- <property name="attributeIds">
- <list>
- <value>eduPersonTargetedID</value>
- </list>
- </property>
- </bean>
- </list>
- </property>
- </bean>
-</beans>
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/attribute/mapping/requestedAttributeValues.xml b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/attribute/mapping/requestedAttributeValues.xml
deleted file mode 100644
index f60a188..0000000
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/attribute/mapping/requestedAttributeValues.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<AttributeConsumingService xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
- xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui"
- xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport" xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"
- xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" index="1">
-
- <ServiceName xml:lang="en">Shibboleth Federated Issue
- Tracking
- </ServiceName>
- <RequestedAttribute FriendlyName="stdFormatFriendly"
- Name="stdFormat" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
- <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xsi:type="xs:string">String</saml:AttributeValue>
- <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xsi:type="xs:boolean">1</saml:AttributeValue>
- <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema">U2NvdCBDYW50b3IgaXMgdGhlIGdvZCBvZiBTQU1M
- </saml:AttributeValue>
- <saml:AttributeValue>scope at scoped.example.org</saml:AttributeValue>
- <saml:AttributeValue>
- <mdui:UIInfo>
- <mdui:DisplayName xml:lang="en">Shibboleth.net
- </mdui:DisplayName>
- <mdui:Description xml:lang="en">An identity provider
- hosted and used by the developers of Shibboleth.
- </mdui:Description>
- <mdui:Logo height="82" width="64">https://discovery.shibboleth.net/images/gryphon_64x82.png
- </mdui:Logo>
- </mdui:UIInfo>
- <mdui:UIInfo>
- <mdui:DisplayName xml:lang="en">Shibboleth.net
- </mdui:DisplayName>
- <mdui:Description xml:lang="en">An identity provider
- hosted and used by the developers of Shibboleth.
- </mdui:Description>
- <mdui:Logo height="82" width="64">https://discovery.shibboleth.net/images/gryphon_64x82.png
- </mdui:Logo>
- </mdui:UIInfo>
- </saml:AttributeValue>
- </RequestedAttribute>
- <RequestedAttribute FriendlyName="oddFormatFriendly"
- Name="oddFormat" NameFormat="https://example.org/" />
- <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">
- <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xsi:type="xs:string">String</saml:AttributeValue>
- </RequestedAttribute>
-</AttributeConsumingService>
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/AttributeQuery.xml b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/AttributeQuery.xml
index 960a449..71d44c4 100644
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/AttributeQuery.xml
+++ b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/AttributeQuery.xml
@@ -4,11 +4,16 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:oasis:names:tc:SAML:2.0:assertion"
Version="2.0" ID="AQ" IssueInstant="2018-03-14T17:31:00Z">
- <Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" FriendlyName="eduPersonAssurance">
+ <Issuer>me</Issuer>
+ <Subject>
+ <NameID>you</NameID>
+ </Subject>
+ <Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="eduPersonAssurance">
<AttributeValue xsi:type="xs:string">turquoise</AttributeValue>
</Attribute>
- <Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" FriendlyName="eduPersonScopedAffiliation">
+ <Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="eduPersonScopedAffiliation">
<AttributeValue xsi:type="xs:string">blue#yellow</AttributeValue>
</Attribute>
- <Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" FriendlyName="eduPersonTargetedID"/>
+ <Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" FriendlyName="eduPersonTargetedID"/>
+ <Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" FriendlyName="eduPersonTargetedIDWithWrongNameFormat"/>
</saml2p:AttributeQuery>
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/AttributeQuerySaml1.xml b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/AttributeQuerySaml1.xml
index 33ccaf8..5bc3446 100644
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/AttributeQuerySaml1.xml
+++ b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/AttributeQuerySaml1.xml
@@ -1,15 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
-<saml1p:AttributeQuery xmlns:saml1p="urn:oasis:names:tc:SAML:1.0:protocol" xmlns="urn:oasis:names:tc:SAML:1.0:assertion"
- xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- Version="2.0" ID="AQ" IssueInstant="2018-03-14T17:31:00Z">
- <Subject/>
- <Attribute AttributeName="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" >
- <AttributeValue xsi:type="xs:string">turquoise</AttributeValue>
- </Attribute>
- <Attribute AttributeName="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" >
- <AttributeValue xsi:type="xs:string" >blue at yellow</AttributeValue>
- </Attribute>
- <Attribute AttributeName="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
-</saml1p:AttributeQuery>
+<saml1p:Request xmlns:saml1p="urn:oasis:names:tc:SAML:1.0:protocol" xmlns="urn:oasis:names:tc:SAML:1.0:assertion"
+ MajorVersion="1" MinorVersion="1" RequestID="ID" IssueInstant="2019-05-02T12:00:00">
+ <saml1p:AttributeQuery>
+ <Subject>
+ <NameIdentifier>you</NameIdentifier>
+ </Subject>
+ <AttributeDesignator AttributeName="flooby" AttributeNamespace="basic" />
+ <AttributeDesignator AttributeName="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" AttributeNamespace="basic" />
+ <AttributeDesignator AttributeName="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" AttributeNamespace="basic" />
+ <AttributeDesignator AttributeName="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" AttributeNamespace="basic"/>
+ </saml1p:AttributeQuery>
+</saml1p:Request>
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml1Mapper.xml b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml1Mapper.xml
index a167735..6a2351d 100644
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml1Mapper.xml
+++ b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml1Mapper.xml
@@ -1,78 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ 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">
- <!-- This is what we are trying to reverse map (note bi-directional aliasing, just to confuse things. And me.
-
- <AttributeDefinition xsi:type="ad:Simple" id="eduPersonAssurance" >
- <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAssurance" />
- </AttributeDefinition>
+ <bean id="shibboleth.IdentifiableBeanPostProcessor"
+ class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
- <AttributeDefinition xsi:type="ad:Simple" id="otherPersonAssurance" >
- <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAssurance" />
- </AttributeDefinition>
-
- <AttributeDefinition xsi:type="ad:Scoped" id="eduPersonScopedAffiliation" scope="example.org" >
- <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" />
- </AttributeDefinition>
-
- <AttributeDefinition xsi:type="ad:SAML2NameID" id="eduPersonTargetedID"
- nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
- <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" />
- </AttributeDefinition>
-
-
+ <bean id="SAML1StringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1StringAttributeTranscoder" />
+ <bean id="SAML1ScopedStringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ScopedStringAttributeTranscoder" />
+
+ <bean id="shibboleth.TranscodingRule"
+ class="net.shibboleth.idp.attribute.transcoding.TranscodingRule" abstract="true" />
+
+ <util:list id="DefaultAttributeRegistry">
+
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="eduPersonAssurance" />
+ <entry key="transcoder" value-ref="SAML1StringTranscoder" />
+ <entry key="name" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" />
+ <entry key="namespace" value="basic" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="eduPersonAssurance" />
+ <entry key="transcoder" value-ref="SAML1StringTranscoder" />
+ <entry key="name" value="http://example.org/name/for/Attribute" />
+ <entry key="namespace" value="basic" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="otherPersonAssurance" />
+ <entry key="transcoder" value-ref="SAML1StringTranscoder" />
+ <entry key="name" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" />
+ <entry key="namespace" value="basic" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="eduPersonScopedAffiliation" />
+ <entry key="transcoder" value-ref="SAML1ScopedStringTranscoder" />
+ <entry key="name" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" />
+ <entry key="namespace" value="basic" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="eduPersonTargetedID" />
+ <entry key="transcoder" value-ref="SAML1ScopedStringTranscoder" />
+ <entry key="name" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" />
+ <entry key="namespace" value="basic" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ </util:list>
- -->
-
- <bean id="abstractStringMapper" init-method="initialize" abstract="true"
- class="net.shibboleth.idp.saml.attribute.mapping.impl.SAML1AttributeDesignatorMapper">
- </bean>
+ <util:map id="DefaultNamingRegistry">
+ <entry key="#{T(org.opensaml.saml.saml1.core.AttributeDesignator)}">
+ <bean class="net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder.NamingFunction" />
+ </entry>
+ </util:map>
+
- <bean id="AttributesMapper"
- class="net.shibboleth.idp.saml.attribute.mapping.impl.SAML1AttributeDesignatorsMapper"
- init-method="initialize" p:id="SAML1AttributesMapper">
- <property name="mappers">
- <list>
- <bean parent="abstractStringMapper">
- <property name="id" value="eduPersonAssurance" />
- <property name="SAMLName" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" />
- <property name="attributeIds">
- <list>
- <value>eduPersonAssurance</value>
- <value>otherPersonAssurance</value>
- </list>
- </property>
- </bean>
- <bean parent="abstractStringMapper">
- <property name="SAMLName" value="http://example.org/name/for/Attribute" />
- <property name="id" value="otherSAMLName" />
- <property name="attributeIds">
- <list>
- <value>eduPersonAssurance</value>
- </list>
- </property>
- </bean>
- <bean parent="abstractStringMapper">
- <property name="sAMLName" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" />
- <property name="id" value="eduPersonScopedAffiliation" />
- <property name="attributeIds">
- <list>
- <value>eduPersonScopedAffiliation</value>
- </list>
- </property>
- </bean>
- <bean parent="abstractStringMapper">
- <property name="sAMLName" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
- <property name="id" value="eduPersonTargetedID"/>
- <property name="attributeIds">
- <list>
- <value>eduPersonTargetedID</value>
- </list>
- </property>
- </bean>
- </list>
- </property>
- </bean>
+ <bean id="AttributeTranscoderRegistry" class="net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl"
+ p:namingRegistry-ref="DefaultNamingRegistry"
+ p:transcoderRegistry-ref="DefaultAttributeRegistry" />
+
</beans>
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml2Mapper.xml b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml2Mapper.xml
index 0dc5069..d7543da 100644
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml2Mapper.xml
+++ b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml2Mapper.xml
@@ -1,96 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ 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">
- <!-- This is what we are trying to reverse map (note bi-directional aliasing, just to confuse things. And me.
-
- <AttributeDefinition xsi:type="ad:Simple" id="eduPersonAssurance" >
- <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" friendlyName="eduPersonAssurance" />
- <AttributeEncoder xsi:type="SAML2String" nameFormat="http://example.org/Format" name="http://example.org/name/for/Attribute" friendlyName="otherSAMLName" />
- </AttributeDefinition>
+ <bean id="shibboleth.IdentifiableBeanPostProcessor"
+ class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
- <AttributeDefinition xsi:type="ad:Simple" id="otherPersonAssurance" >
- <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" friendlyName="eduPersonAssurance" />
- </AttributeDefinition>
-
- <AttributeDefinition xsi:type="ad:Scoped" id="eduPersonScopedAffiliation" scope="example.org" >
- <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" friendlyName="eduPersonScopedAffiliation"
- scopeDelimiter='#'/>
- </AttributeDefinition>
-
- <AttributeDefinition xsi:type="ad:SAML2NameID" id="eduPersonTargetedID"
- nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
- <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="eduPersonTargetedID" />
- </AttributeDefinition>
-
-
+ <bean id="SAML2StringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2StringAttributeTranscoder" />
+ <bean id="SAML2ScopedStringTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ScopedStringAttributeTranscoder" />
+ <bean id="SAML2XMLObjectTranscoder"
+ class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2XMLObjectAttributeTranscoder" />
+
+ <bean id="shibboleth.TranscodingRule"
+ class="net.shibboleth.idp.attribute.transcoding.TranscodingRule" abstract="true" />
+
+ <util:list id="DefaultAttributeRegistry">
- -->
-
- <bean id="abstractStringMapper" init-method="initialize" abstract="true"
- class="net.shibboleth.idp.saml.attribute.mapping.impl.SAML2AttributeMapper">
- <property name="valueMapper">
- <bean
- class="net.shibboleth.idp.saml.attribute.mapping.impl.StringAttributeValueMapper" />
- </property>
- </bean>
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="eduPersonAssurance" />
+ <entry key="transcoder" value-ref="SAML2StringTranscoder" />
+ <entry key="name" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="eduPersonAssurance" />
+ <entry key="transcoder" value-ref="SAML2StringTranscoder" />
+ <entry key="name" value="http://example.org/name/for/Attribute" />
+ <entry key="nameFormat" value="http://example.org/Format" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="otherPersonAssurance" />
+ <entry key="transcoder" value-ref="SAML2StringTranscoder" />
+ <entry key="name" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="eduPersonScopedAffiliation" />
+ <entry key="transcoder" value-ref="SAML2ScopedStringTranscoder" />
+ <entry key="scopeDelimiter" value="#" />
+ <entry key="name" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingRule">
+ <constructor-arg>
+ <map>
+ <entry key="id" value="eduPersonTargetedID" />
+ <entry key="transcoder" value-ref="SAML2XMLObjectTranscoder" />
+ <entry key="name" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" />
+ </map>
+ </constructor-arg>
+ </bean>
+
+ </util:list>
+
+ <util:map id="DefaultNamingRegistry">
+ <entry key="#{T(org.opensaml.saml.saml2.core.Attribute)}">
+ <bean class="net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder.NamingFunction" />
+ </entry>
+ </util:map>
+
- <bean id="AttributesMapper"
- class="net.shibboleth.idp.saml.attribute.mapping.impl.SAML2AttributesMapper"
- init-method="initialize" p:id="SAML2AttributesMapper">
- <property name="mappers">
- <list>
- <bean parent="abstractStringMapper">
- <property name="id" value="eduPersonAssurance" />
- <property name="SAMLName" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" />
- <property name="attributeIds">
- <list>
- <value>eduPersonAssurance</value>
- <value>otherPersonAssurance</value>
- </list>
- </property>
- </bean>
- <bean parent="abstractStringMapper">
- <property name="SAMLName" value="http://example.org/name/for/Attribute" />
- <property name="id" value="otherSAMLName" />
- <property name="attributeFormat" value="http://example.org/Format " />
- <property name="attributeIds">
- <list>
- <value>eduPersonAssurance</value>
- </list>
- </property>
- </bean>
- <bean parent="abstractStringMapper">
- <property name="sAMLName" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" />
- <property name="id" value="eduPersonScopedAffiliation" />
- <property name="attributeFormat" value=" format " />
- <property name="valueMapper">
- <bean
- class="net.shibboleth.idp.saml.attribute.mapping.impl.ScopedStringAttributeValueMapper"
- p:delimiter="#" />
- </property>
- <property name="attributeIds">
- <list>
- <value>eduPersonScopedAffiliation</value>
- </list>
- </property>
- </bean>
- <bean parent="abstractStringMapper">
- <property name="attributeFormat" value="format"/>
- <property name="sAMLName" value="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
- <property name="id" value="eduPersonTargetedID"/>
- <property name="valueMapper">
- <bean
- class="net.shibboleth.idp.saml.attribute.mapping.impl.XMLObjectAttributeValueMapper" />
- </property>
- <property name="attributeIds">
- <list>
- <value>eduPersonTargetedID</value>
- </list>
- </property>
- </bean>
- </list>
- </property>
- </bean>
+ <bean id="AttributeTranscoderRegistry" class="net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl"
+ p:namingRegistry-ref="DefaultNamingRegistry"
+ p:transcoderRegistry-ref="DefaultAttributeRegistry" />
+
</beans>
diff --git a/idp-schema/.project b/idp-schema/.project
index c89db8c..dc76e99 100644
--- a/idp-schema/.project
+++ b/idp-schema/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-schema/src/main/resources/schema/shibboleth-afp.xsd b/idp-schema/src/main/resources/schema/shibboleth-afp.xsd
index 7ca9682..dc202a7 100644
--- a/idp-schema/src/main/resources/schema/shibboleth-afp.xsd
+++ b/idp-schema/src/main/resources/schema/shibboleth-afp.xsd
@@ -751,11 +751,16 @@
</complexContent>
</complexType>
- <complexType name="AttributeInMetadataType" abstract="true">
+ <complexType name="AttributeInMetadata">
<annotation>
<documentation>
- Functions that evaluate to true if an attribute (or specific values) is specified by
- supplied metadata.
+ A match function that evaluates to true if an attribute (or specific values) is specified by
+ the requesting entity's AttributeConsumingService SP metadata.
+
+ It supports both explicit checking for a named SAML RequestedAttribute in metadata, or
+ comparison via the transcoding registry to compare the internal attribute form against
+ decoded objects produced from the metadata. This is the old "mapped" functionality
+ in V3 and is now collapsed into one matcher type.
</documentation>
</annotation>
<complexContent>
@@ -783,29 +788,21 @@
</documentation>
</annotation>
</attribute>
- </extension>
- </complexContent>
- </complexType>
-
- <complexType name="AttributeInMetadata">
- <annotation>
- <documentation>
- A match function that evaluates to true if an attribute (or specific values) is specified by
- the requesting entity's AttributeConsumingService SP metadata.
- </documentation>
- </annotation>
- <complexContent>
- <extension base="afp:AttributeInMetadataType">
- <attribute name="attributeName" type="string" use="optional">
+ <attribute name="attributeName" type="string">
<annotation>
<documentation>The name of a requested attribute to look for.</documentation>
</annotation>
</attribute>
- <attribute name="attributeNameFormat" type="string" use="optional">
+ <attribute name="attributeNameFormat" type="string">
<annotation>
<documentation>The name format of a requested attribute to look for.</documentation>
</annotation>
</attribute>
+ <attribute name="objectStrategyRef" type="string">
+ <annotation>
+ <documentation>Reference to locate XMLObject source of mapped attributes.</documentation>
+ </annotation>
+ </attribute>
</extension>
</complexContent>
</complexType>
@@ -813,18 +810,11 @@
<complexType name="MappedAttributeInMetadata">
<annotation>
<documentation>
- A match function that evaluates to true if a mapped attribute (or specific values) is specified by
- the requesting entity's AttributeConsumingService SP metadata.
+ Deprecated alias for afp:AttributeInMetadata type.
</documentation>
</annotation>
<complexContent>
- <extension base="afp:AttributeInMetadataType">
- <attribute name="objectStrategyRef" type="string" use="optional">
- <annotation>
- <documentation>Reference to locate XMLObject source of mapped attributes.</documentation>
- </annotation>
- </attribute>
- </extension>
+ <extension base="afp:AttributeInMetadata" />
</complexContent>
</complexType>
diff --git a/idp-session-api/.project b/idp-session-api/.project
index 62a1f7f..5e64ebd 100644
--- a/idp-session-api/.project
+++ b/idp-session-api/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-session-impl/.project b/idp-session-impl/.project
index 8a48a91..eae928f 100644
--- a/idp-session-impl/.project
+++ b/idp-session-impl/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-ui/.project b/idp-ui/.project
index b903b34..a5da135 100644
--- a/idp-ui/.project
+++ b/idp-ui/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-war/.project b/idp-war/.project
index 3f1824d..5294722 100644
--- a/idp-war/.project
+++ b/idp-war/.project
@@ -16,11 +16,6 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
diff --git a/idp-war/src/main/webapp/WEB-INF/jsp/status.jsp b/idp-war/src/main/webapp/WEB-INF/jsp/status.jsp
index 7371f15..5e41cde 100644
--- a/idp-war/src/main/webapp/WEB-INF/jsp/status.jsp
+++ b/idp-war/src/main/webapp/WEB-INF/jsp/status.jsp
@@ -13,6 +13,7 @@
<%@ page import="net.shibboleth.idp.Version" %>
<%@ page import="net.shibboleth.idp.saml.metadata.RelyingPartyMetadataProvider" %>
<%@ page import="net.shibboleth.idp.attribute.resolver.AttributeResolver" %>
+<%@ page import="net.shibboleth.idp.attribute.resolver.impl.AttributeResolverImpl" %>
<%@ page import="net.shibboleth.idp.attribute.resolver.DataConnector" %>
<%@ page import="net.shibboleth.utilities.java.support.component.IdentifiedComponent" %>
<%@ page import="net.shibboleth.utilities.java.support.service.ReloadableService" %>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list