[java-oidc-common] branch main updated: JCOMOIDC-154 - Mechanism for invalidating current metadata cache contents

Codeberg noreply at shibboleth.net
Mon Sep 28 10:51:57 UTC 2026


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

codeberg pushed a commit to branch main
in repository java-oidc-common.

View the commit online:
https://codeberg.org/Shibboleth/java-oidc-common/commit/f1c87f1041560910a68fa88836a5122bcc983719

The following commit(s) were added to refs/heads/main by this push:
     new f1c87f10 JCOMOIDC-154 - Mechanism for invalidating current metadata cache contents
f1c87f10 is described below

commit f1c87f1041560910a68fa88836a5122bcc983719
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Mon Sep 28 11:51:49 2026 +0100

    JCOMOIDC-154 - Mechanism for invalidating current metadata cache
    contents
    
     - Add a clearAll mechanism to the MetadataCache which defaults to a
    no-op implementation.
    
    https://shibboleth.atlassian.net/browse/JCOMOIDC-154
---
 .../oidc/metadata/cache/MetadataCache.java         | 18 ++++++++++
 .../metadata/cache/impl/BatchMetadataCache.java    | 16 +++++++++
 .../metadata/cache/impl/DynamicMetadataCache.java  | 40 +++++++++++++++++++++-
 .../cache/impl/BatchMetadataCacheTest.java         | 21 ++++++++++++
 .../cache/impl/DynamicMetadataCacheTest.java       | 14 ++++++++
 5 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/oidc-common-metadata-api/src/main/java/net/shibboleth/oidc/metadata/cache/MetadataCache.java b/oidc-common-metadata-api/src/main/java/net/shibboleth/oidc/metadata/cache/MetadataCache.java
index 99f03a50..a53ef19b 100644
--- a/oidc-common-metadata-api/src/main/java/net/shibboleth/oidc/metadata/cache/MetadataCache.java
+++ b/oidc-common-metadata-api/src/main/java/net/shibboleth/oidc/metadata/cache/MetadataCache.java
@@ -47,5 +47,23 @@ public interface MetadataCache<U> {
      */
     @Nonnull @NonnullElements public List<U> get(@Nonnull @NotEmpty final CriteriaSet criteria)
             throws MetadataCacheException;
+    
+    /**
+     * Clear all entries from the cache.
+     * 
+     * <p>The default, for implementations that do not override this method, is false: the cache has not been
+     * cleared.</p>
+     * 
+     * <p>The implementing method is required to be thread safe.</p>
+     * 
+     * @return true if all entries of the cache were successfully cleared, false otherwise.
+     * 
+     * @since 3.4.0
+     * 
+     * TODO: remove the default in 4.0.0
+     */
+    default boolean clearAll() {
+    	return false;
+    }
 
 }
diff --git a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/cache/impl/BatchMetadataCache.java b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/cache/impl/BatchMetadataCache.java
index 8c91f316..fc2cef7f 100644
--- a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/cache/impl/BatchMetadataCache.java
+++ b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/cache/impl/BatchMetadataCache.java
@@ -369,6 +369,22 @@ public class BatchMetadataCache<IdentifierType, MetadataType>
         return new CacheLoadingContext(getBackingStore().getLastUpdate(), getBackingStore().getLastRefresh());
     }
     
+    
+    @Override
+    public boolean clearAll() {
+    	 readWriteLock.writeLock().lock();
+         try {
+        	 log.debug("{} Clearing all entries from the cache", getLogPrefix());
+        	 invalidateAll();
+        	 return true;
+         } catch (final Exception e){
+        	 log.error("{} Unable to clear cache entries", getLogPrefix(), e);
+        	 return false;
+         } finally {
+             readWriteLock.writeLock().unlock();
+         }    	
+    }
+    
     /**
      * Reload the entire backing-store cache using the loading strategy.
      * 
diff --git a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/cache/impl/DynamicMetadataCache.java b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/cache/impl/DynamicMetadataCache.java
index dc0de286..104e71d5 100644
--- a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/cache/impl/DynamicMetadataCache.java
+++ b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/cache/impl/DynamicMetadataCache.java
@@ -17,6 +17,7 @@ package net.shibboleth.oidc.metadata.cache.impl;
 
 import java.time.Duration;
 import java.time.Instant;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -437,6 +438,44 @@ public class DynamicMetadataCache<IdentifierType, MetadataType>
             MetricsSupport.stopTimer(contextResolve);
         }
             
+    }    
+
+    /**
+     * {@inheritDoc}
+     * 
+     * <p>Clearing a dynamic cache, using per entity locking, does not guarantee the cache is cleared by the point
+     * the method returns to the caller. That is, another entity may have been added during cache clearance: there
+     * is no overall locking of the cache.</p>
+     * 
+     * <p>Consequently, the returned boolean cannot be used to determine whether the cache is empty. It indicates
+     * only whether all entries present in the backing store at the start of execution were successfully
+     * invalidated.</p> 
+     */
+    @Override
+    public boolean clearAll() {    	
+    	// Use a new arraylist of identifiers, so we do not iterate and remove over the same list 
+    	 final var identifiers =
+    			new ArrayList<>(getBackingStore().getIndexedValues().keySet());
+    	
+    	 boolean allCleared = true;
+		 for (final var identifier : identifiers) {			
+			 final MetadataManagementData<IdentifierType> mgmtData = getBackingStore().getManagementData(identifier);
+			 if (mgmtData == null) {
+				 log.warn("{} No management data found for cache entry '{}', unable to remove",  
+						 getLogPrefix(), identifier);
+				 allCleared = false;
+				 continue;
+			 }
+			 final StampedLock sl = mgmtData.getStampLock();
+			 final long stamp = sl.writeLock();    	        
+			 try {            
+			 	invalidate(identifier);   
+			 	getBackingStore().removeManagementData(identifier);
+			 } finally {
+			     sl.unlock(stamp);
+			 } 
+		 }
+    	 return allCleared;
     }
     
     /**
@@ -651,7 +690,6 @@ public class DynamicMetadataCache<IdentifierType, MetadataType>
         }
         
     }
-
     
     /**
      * Cleanup task that removes expired and idle metadata from the backing store.
diff --git a/oidc-common-metadata-impl/src/test/java/net/shibboleth/oidc/metadata/cache/impl/BatchMetadataCacheTest.java b/oidc-common-metadata-impl/src/test/java/net/shibboleth/oidc/metadata/cache/impl/BatchMetadataCacheTest.java
index 4e1ca562..353240dc 100644
--- a/oidc-common-metadata-impl/src/test/java/net/shibboleth/oidc/metadata/cache/impl/BatchMetadataCacheTest.java
+++ b/oidc-common-metadata-impl/src/test/java/net/shibboleth/oidc/metadata/cache/impl/BatchMetadataCacheTest.java
@@ -431,6 +431,27 @@ public class BatchMetadataCacheTest {
         Thread.sleep(10000);
 
     }
+    
+    @Test
+    public void testClearingCache() throws Exception {
+    	cache.initialize();
+    	
+    	final Issuer iss = new Issuer("http://www.example.org");
+    	// Add an entry
+        cache.getBackingStore().getIndexedValues().put(iss, List.of(
+                new OIDCProviderMetadata(new Issuer("http://www.example.org"), List.of(SubjectType.PUBLIC),
+                new URI("http://www.example.org/metadata"))));
+        List<OIDCProviderMetadata> metadata =
+                cache.get(new CriteriaSet(new IssuerIDCriterion(new Issuer("http://www.example.org"))));
+        assertTrue(metadata.isEmpty() == false);
+        
+        // Now clear the cache
+        assertTrue(cache.clearAll());
+        
+        metadata = cache.get(new CriteriaSet(new IssuerIDCriterion(new Issuer("http://www.example.org"))));
+        assertTrue(metadata.isEmpty() == true);
+        
+    }
 
     @Test
     public void testGetAndLoad_Success()throws Exception {
diff --git a/oidc-common-metadata-impl/src/test/java/net/shibboleth/oidc/metadata/cache/impl/DynamicMetadataCacheTest.java b/oidc-common-metadata-impl/src/test/java/net/shibboleth/oidc/metadata/cache/impl/DynamicMetadataCacheTest.java
index 9853a623..61d11955 100644
--- a/oidc-common-metadata-impl/src/test/java/net/shibboleth/oidc/metadata/cache/impl/DynamicMetadataCacheTest.java
+++ b/oidc-common-metadata-impl/src/test/java/net/shibboleth/oidc/metadata/cache/impl/DynamicMetadataCacheTest.java
@@ -333,6 +333,20 @@ public class DynamicMetadataCacheTest {
 
     }
     
+    @Test
+    public void testClearAll() throws MetadataCacheException, ComponentInitializationException {
+        cache.initialize();
+        final List<OIDCProviderMetadata> metadata = 
+                cache.get(new CriteriaSet(new IssuerIDCriterion(new Issuer("the-issuer"))));
+        assertTrue(metadata.isEmpty() == false);
+        assertFalse(cache.getBackingStore().getIndexedValues().isEmpty());
+        assertFalse(cache.getBackingStore().getOrderedValues().isEmpty());
+        assertTrue(cache.clearAll());
+        assertTrue(cache.getBackingStore().getIndexedValues().isEmpty());
+        assertTrue(cache.getBackingStore().getOrderedValues().isEmpty());
+        assertTrue(cache.getBackingStore().getManagementDataIdentifiers().isEmpty());
+    }
+    
     @Test
     public void testGetNotCached_WrongIdentifier_Fail() throws MetadataCacheException, ComponentInitializationException {
         final ManuallyTriggeredScheduledExecutorService scheduler = new ManuallyTriggeredScheduledExecutorService();

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


More information about the commits mailing list