From 8cdbef594e717639653ee2a995a5fded05436f75 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Fri, 7 Sep 2018 13:14:59 -0700 Subject: [PATCH] [SHIBUI-570] Added simple caching of fetchMetdata and unmarshallMetadata. --- .../MetadataResolversController.java | 2 + ...penSamlFileBackedHTTPMetadataResolver.java | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java index 4d7d7aaac..2b4b90d65 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java @@ -118,6 +118,8 @@ public ResponseEntity create(@RequestBody MetadataResolver newResolver) throw MetadataResolver persistedResolver = resolverRepository.save(newResolver); positionOrderContainerService.appendPositionOrderForNew(persistedResolver); + //TODO: currently, the update call might explode, but the save works.. in which case, the UI never gets + // an valid response. This operation is not atomic. Should we return an error here? updateChainingMetadataResolver(persistedResolver); return ResponseEntity.created(getResourceUriFor(persistedResolver)).body(persistedResolver); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java index 5f4c10905..e74bff535 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java @@ -8,21 +8,35 @@ import org.apache.http.impl.client.HttpClients; import org.apache.lucene.index.IndexWriter; import org.joda.time.DateTime; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.io.UnmarshallingException; import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.io.InputStream; +import java.time.Instant; + import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis; /** * @author Bill Smith (wsmith@unicon.net) */ public class OpenSamlFileBackedHTTPMetadataResolver extends FileBackedHTTPMetadataResolver { + + private static final long MILLISECONDS_IN_ONE_SECOND = 1000; + private IndexWriter indexWriter; private FileBackedHttpMetadataResolver sourceResolver; private OpenSamlMetadataResolverDelegate delegate; + private byte[] cachedMetadataBytes; + private Instant metadataLastFetchedAt; + boolean shouldRefreshMetadata; + XMLObject cachedMetadata; + public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, IndexWriter indexWriter, FileBackedHttpMetadataResolver sourceResolver) throws ResolverException { @@ -67,4 +81,31 @@ protected void initMetadataResolver() throws ComponentInitializationException { this.sourceResolver.getResourceId(), indexWriter); } + + @Override + protected byte[] fetchMetadata() throws ResolverException { + if (metadataLastFetchedAt == null || shouldRefreshMetadata()) { + this.cachedMetadataBytes = super.fetchMetadata(); + this.metadataLastFetchedAt = Instant.now(); + } + return cachedMetadataBytes; + } + + private boolean shouldRefreshMetadata() { + if ((Instant.now().getEpochSecond() - metadataLastFetchedAt.getEpochSecond()) > (this.getMinRefreshDelay() / MILLISECONDS_IN_ONE_SECOND)) { + shouldRefreshMetadata = true; + } + return shouldRefreshMetadata; + } + + @Override + protected XMLObject unmarshallMetadata(@Nonnull final InputStream metadataInput) + throws UnmarshallingException { + //TODO: This should probably be based on something other than minRefreshDelay + if (cachedMetadata == null || shouldRefreshMetadata) { + this.cachedMetadata = super.unmarshallMetadata(metadataInput); + this.shouldRefreshMetadata = false; + } + return this.cachedMetadata; + } }