Java tutorial
/* * 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.impl.ad.mapped; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; import net.shibboleth.idp.attribute.IdPAttribute; import net.shibboleth.idp.attribute.IdPAttributeValue; import net.shibboleth.idp.attribute.StringAttributeValue; import net.shibboleth.idp.attribute.UnsupportedAttributeTypeException; import net.shibboleth.idp.attribute.resolver.AbstractAttributeDefinition; import net.shibboleth.idp.attribute.resolver.PluginDependencySupport; import net.shibboleth.idp.attribute.resolver.ResolutionException; import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext; import net.shibboleth.idp.attribute.resolver.context.AttributeResolverWorkContext; import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements; 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.LazySet; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; /** * Implementation of Mapped Attributes. <br/> * An attribute definition that takes the values from previous resolution stages and converts them as it creates the * output attribute. Each value is compared with a lookup table (a {@link java.util.Collection} of @link{ValueMap}s) and * if it matches then the appropriate value(s) is/are substituted. Non matches are either passed through or are removed * depending on the setting 'passThru'. * */ @ThreadSafe public class MappedAttributeDefinition extends AbstractAttributeDefinition { /** Class logger. */ private final Logger log = LoggerFactory.getLogger(MappedAttributeDefinition.class); /** Value maps. */ private Set<ValueMap> valueMaps = Collections.emptySet(); /** Whether the definition passes thru unmatched values. */ private boolean passThru; /** Default return value. */ @Nullable private StringAttributeValue defaultValue; /** * Gets the functions used to map an input value to an output value. * * @return functions used to map an input value to an output value */ @Nonnull @NonnullElements @Unmodifiable public Collection<ValueMap> getValueMaps() { return valueMaps; } /** * Sets the functions used to map an input value to an output value. * * @param mappings functions used to map an input value to an output value */ public synchronized void setValueMaps(@Nullable @NullableElements final Collection<ValueMap> mappings) { ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this); ComponentSupport.ifDestroyedThrowDestroyedComponentException(this); valueMaps = ImmutableSet.copyOf(Iterables.filter(mappings, Predicates.notNull())); } /** * Gets the default return value. * * @return the default return value. */ @Nullable public StringAttributeValue getDefaultAttributeValue() { return defaultValue; } /** * Gets the default return value. * * @return the default return value. */ @Nullable public String getDefaultValue() { if (null == defaultValue) { return null; } return defaultValue.getValue(); } /** * Sets the default return value. * * @param newDefaultValue the default return value */ public void setDefaultValue(@Nullable String newDefaultValue) { ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this); ComponentSupport.ifDestroyedThrowDestroyedComponentException(this); String trimmedDefault = StringSupport.trimOrNull(newDefaultValue); if (null == trimmedDefault) { defaultValue = null; } else { defaultValue = new StringAttributeValue(trimmedDefault); } } /** * Gets whether the definition passes unmatched values through. * * @return whether the definition passes unmatched values unchanged or suppresses them. */ public boolean isPassThru() { return passThru; } /** * Sets whether the definition passes unmatched values through. * * @param newPassThru whether the definition passes unmatched values unchanged or suppresses them. */ public void setPassThru(boolean newPassThru) { ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this); ComponentSupport.ifDestroyedThrowDestroyedComponentException(this); passThru = newPassThru; } /** * Maps the value from a dependency in to the value(s) for this attribute. * * @param value the value from the dependency * * @return the set of attribute values that the given dependency value maps in to */ protected Set<IdPAttributeValue<?>> mapValue(@Nullable String value) { log.debug("Attribute Definition {}: mapping depdenency attribute value {}", getId(), value); final String trimmedValue = StringSupport.trimOrNull(value); final LazySet<IdPAttributeValue<?>> mappedValues = new LazySet<>(); boolean valueMapMatch = false; if (null != trimmedValue) { for (ValueMap valueMap : valueMaps) { mappedValues.addAll(valueMap.apply(value)); if (!mappedValues.isEmpty()) { valueMapMatch = true; } } if (!valueMapMatch) { if (passThru) { mappedValues.add(new StringAttributeValue(value)); } else if (defaultValue != null) { mappedValues.add(defaultValue); } } } log.debug("Attribute Definition {}: mapped depdenency attribute value {} to the values {}", new Object[] { getId(), value, mappedValues, }); return mappedValues; } /** {@inheritDoc} */ @Override @Nullable protected IdPAttribute doAttributeDefinitionResolve(@Nonnull final AttributeResolutionContext resolutionContext, @Nonnull final AttributeResolverWorkContext workContext) throws ResolutionException { ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this); ComponentSupport.ifDestroyedThrowDestroyedComponentException(this); Constraint.isNotNull(resolutionContext, "Attribute resolution context can not be null"); final Set<IdPAttributeValue<?>> unmappedResults = PluginDependencySupport .getMergedAttributeValues(workContext, getDependencies()); log.debug("Attribute Definition '{}': Attempting to map the following values: {}", getId(), unmappedResults); // Bucket for results final IdPAttribute resultAttribute = new IdPAttribute(getId()); if (unmappedResults == null || unmappedResults.isEmpty()) { log.debug("Attribute Definition {}: No values from dependencies", getId()); if (null != defaultValue) { log.debug("Attribute Definition {}: Default value of {} added as the value for this attribute", getId(), defaultValue); resultAttribute.setValues(Collections.singleton(defaultValue)); } } else { final LinkedHashSet<IdPAttributeValue<?>> hs = new LinkedHashSet<>(); for (IdPAttributeValue unmappedValue : unmappedResults) { if (!(unmappedValue instanceof StringAttributeValue)) { throw new ResolutionException(new UnsupportedAttributeTypeException( "Attribute definition '" + getId() + "' does not support dependency values of type " + unmappedValue.getClass().getName())); } hs.addAll(mapValue(((StringAttributeValue) unmappedValue).getValue())); } resultAttribute.setValues(hs); } return resultAttribute; } /** {@inheritDoc} */ @Override protected void doDestroy() { valueMaps = null; super.doDestroy(); } /** {@inheritDoc} */ @Override protected void doInitialize() throws ComponentInitializationException { super.doInitialize(); if (getDependencies().isEmpty()) { throw new ComponentInitializationException( "Attribute definition '" + getId() + "': no dependencies were configured"); } if (valueMaps.isEmpty()) { throw new ComponentInitializationException( "Attribute definition '" + getId() + "': no value mappings were configured"); } } }