package org.apereo.cas.support.saml.services.idp.metadata.cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.LoadingCache; import org.apereo.cas.support.saml.services.SamlRegisteredService; import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.TimeUnit; /** * An adaptation of metadata resolver which handles the resolution of metadata resources * inside a Guava cache. It basically is a fancy wrapper around Guava, and constructs the cache * semantics before processing the resolution of metadata for a SAML service. * * @author Misagh Moayyed * @since 5.0.0 */ public class DefaultSamlRegisteredServiceCachingMetadataResolver implements SamlRegisteredServiceCachingMetadataResolver { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSamlRegisteredServiceCachingMetadataResolver.class); private long metadataCacheExpirationMinutes; private ChainingMetadataResolverCacheLoader chainingMetadataResolverCacheLoader; private LoadingCache<SamlRegisteredService, ChainingMetadataResolver> cache; public DefaultSamlRegisteredServiceCachingMetadataResolver(final long metadataCacheExpirationMinutes, final ChainingMetadataResolverCacheLoader chainingMetadataResolverCacheLoader) { this.metadataCacheExpirationMinutes = metadataCacheExpirationMinutes; this.chainingMetadataResolverCacheLoader = chainingMetadataResolverCacheLoader; this.cache = CacheBuilder.newBuilder().maximumSize(1) .expireAfterWrite(this.metadataCacheExpirationMinutes, TimeUnit.MINUTES).build(this.chainingMetadataResolverCacheLoader); } @Override public ChainingMetadataResolver resolve(final SamlRegisteredService service) { ChainingMetadataResolver resolver = null; try { LOGGER.debug("Resolving metadata for [{}] at [{}].", service.getName(), service.getMetadataLocation()); resolver = this.cache.get(service); return resolver; } catch (final Exception e) { throw new IllegalArgumentException("Metadata resolver could not be located from metadata " + service.getMetadataLocation(), e); } finally { if (resolver != null) { LOGGER.debug("Loaded and cached SAML metadata [{}] from [{}] for [{}] minute(s)", resolver.getId(), service.getMetadataLocation(), this.metadataCacheExpirationMinutes); } } } public void setChainingMetadataResolverCacheLoader(final ChainingMetadataResolverCacheLoader chainingMetadataResolverCacheLoader) { this.chainingMetadataResolverCacheLoader = chainingMetadataResolverCacheLoader; } public void setMetadataCacheExpirationMinutes(final long metadataCacheExpirationMinutes) { this.metadataCacheExpirationMinutes = metadataCacheExpirationMinutes; } }