This is an automated email from the ASF dual-hosted git repository.

rvesse pushed a commit to branch gh-2230
in repository https://gitbox.apache.org/repos/asf/jena.git

commit 6633e7bfd6c6865854d5163905e17d502dd3ec0a
Author: Rob Vesse <[email protected]>
AuthorDate: Thu Mar 14 14:35:59 2024 +0000

    GH-2230: Replace ExpiringMap with Cache API
    
    Replaces the usage of the ExpiringMap API with Jena's existing Cache
    API, this entails some related changes to the configuration portions of
    the GeoSPARQL module.
---
 .../apache/jena/atlas/lib/cache/CacheCaffeine.java |   7 +
 .../github/galbiston/expiring_map/ExpiringMap.java | 350 ---------------
 .../galbiston/expiring_map/ExpiringMap2.java       |  46 --
 .../galbiston/expiring_map/ExpiringMapCleaner.java |  98 -----
 .../galbiston/expiring_map/ExpiringMaps.java       |  28 --
 .../galbiston/expiring_map/KeyTimestampPair.java   | 106 -----
 .../galbiston/expiring_map/MapDefaultValues.java   |  35 --
 .../geosparql/configuration/GeoSPARQLConfig.java   |  40 +-
 .../implementation/index/CacheConfiguration.java   |  67 +++
 .../implementation/index/GeometryLiteralIndex.java |  58 +--
 .../index/GeometryTransformIndex.java              |  41 +-
 .../implementation/index/IndexConfiguration.java   |  40 +-
 .../implementation/index/QueryRewriteIndex.java    |  73 +---
 .../galbiston/expiring_map/ExpiringMapTest.java    | 475 ---------------------
 .../index/CacheConfigurationTest.java              |  79 ++++
 15 files changed, 208 insertions(+), 1335 deletions(-)

diff --git 
a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheCaffeine.java 
b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheCaffeine.java
index 73426e92f8..9f6721f5b7 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheCaffeine.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheCaffeine.java
@@ -131,5 +131,12 @@ final public class CacheCaffeine<K,V> implements Cache<K, 
V>
     public long size() {
         return cache.estimatedSize() ;
     }
+
+    /**
+     * Forces the cache to clean up stale entries
+     */
+    public void cleanUp() {
+        this.cache.cleanUp();
+    }
 }
 
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMap.java
 
b/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMap.java
deleted file mode 100644
index a64196c7d0..0000000000
--- 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMap.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright 2018 the original author or authors.
- * See the notice.md file distributed with this work for additional
- * information regarding copyright ownership.
- *
- * Licensed 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 org.apache.jena.ext.io.github.galbiston.expiring_map;
-
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.*;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Timer;
-import java.util.concurrent.ConcurrentHashMap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Expiring Map for storage of entries which expire if unused for a period of
- * time.
- * <br>Size of map, duration until expiry and frequency of cleaning can all be
- * controlled.
- *
- * @param <K> Key entry object.
- * @param <V> Value entry object.
- */
-public class ExpiringMap<K, V> extends ConcurrentHashMap<K, V> {
-
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-    private String label;
-    private boolean running;
-    private boolean expiring;
-    private long maxSize;
-    private long expiryInterval;
-    private long cleanerInterval;
-    private long fullMapWarningInterval;
-    private long fullMapWarning;
-    private ExpiringMapCleaner mapCleaner;
-    private Timer cleanerTimer;
-
-    /**
-     * Instance of Expiring Map that will not remove items and has no limit on
-     * size.
-     *
-     * @param label Name of the map.
-     */
-    public ExpiringMap(String label) {
-        this(label, UNLIMITED_MAP, UNLIMITED_EXPIRY, MAP_CLEANER_INTERVAL, 
FULL_MAP_WARNING_INTERVAL);
-    }
-
-    /**
-     * Instance of Expiring Map that will not remove items.
-     *
-     * @param label Name of the map.
-     * @param maxSize Maximum size of the map when items will no longer be 
added
-     * or unlimited size (-1).
-     */
-    public ExpiringMap(String label, int maxSize) {
-        this(label, maxSize, UNLIMITED_EXPIRY, MAP_CLEANER_INTERVAL, 
FULL_MAP_WARNING_INTERVAL);
-    }
-
-    /**
-     * Instance of Expiring Map that will remove items after a period of time
-     * which have not been accessed.
-     *
-     * @param label Name of the map.
-     * @param maxSize Maximum size of the map when items will no longer be
-     * added. Unlimited size (-1) will still remove expired items.
-     * @param expiryInterval Duration that items remain in map.
-     */
-    public ExpiringMap(String label, int maxSize, long expiryInterval) {
-        this(label, maxSize, expiryInterval, MAP_CLEANER_INTERVAL, 
FULL_MAP_WARNING_INTERVAL);
-    }
-
-    /**
-     * Instance of Expiring Map that will remove items after a period of time
-     * which have not been accessed.
-     *
-     * @param label Name of the map.
-     * @param maxSize Maximum size of the map when items will no longer be
-     * added. Unlimited size (-1) will still remove expired items.
-     * @param expiryInterval Duration that items remain in map.
-     * @param cleanerInterval Frequency that items are checked for removal from
-     * map.
-     */
-    public ExpiringMap(String label, int maxSize, long expiryInterval, long 
cleanerInterval) {
-        this(label, maxSize, expiryInterval, cleanerInterval, 
FULL_MAP_WARNING_INTERVAL);
-    }
-
-    /**
-     * Instance of Expiring Map that will remove items after a period of time
-     * which have not been accessed.
-     *
-     * @param label Name of the map.
-     * @param maxSize Maximum size of the map when items will no longer be
-     * added. Unlimited size (-1) will still remove expired items.
-     * @param expiryInterval Duration that items remain in map.
-     * @param cleanerInterval Frequency that items are checked for removal from
-     * map.
-     * @param fullMapWarningInterval Full map warning frequency.
-     */
-    public ExpiringMap(String label, int maxSize, long expiryInterval, long 
cleanerInterval, long fullMapWarningInterval) {
-        super(maxSize > UNLIMITED_MAP ? maxSize : UNLIMITED_INITIAL_CAPACITY);
-        this.label = label;
-        setMaxSize(maxSize);
-        this.running = false;
-        this.expiring = false;
-        this.cleanerTimer = null;
-        this.mapCleaner = null;
-        setCleanerInterval(cleanerInterval);
-        setExpiryInterval(expiryInterval); //Can set expiryInterval, 
mapCleaner and expiring.
-        this.fullMapWarningInterval = fullMapWarningInterval;
-        this.fullMapWarning = System.currentTimeMillis();
-
-    }
-
-    @Override
-    public V put(K key, V value) {
-        if (super.mappingCount() < maxSize) {
-            mapCleaner.put(key);
-            return super.put(key, value);
-        } else {
-            long currentSystemTime = System.currentTimeMillis();
-            long difference = currentSystemTime - fullMapWarning;
-            if (difference > fullMapWarningInterval) {
-                fullMapWarning = currentSystemTime;
-                LOGGER.warn("{} Map Full: {} - Warning suppressed for {}ms", 
label, maxSize, fullMapWarningInterval);
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public boolean containsKey(Object key) {
-        boolean isContained = super.containsKey(key);
-        if (isContained) {
-            mapCleaner.refresh(key);
-        }
-        return isContained;
-    }
-
-    @Override
-    public V get(Object key) {
-        V value = super.get(key);
-        if (value != null) {
-            mapCleaner.refresh(key);
-        }
-        return value;
-    }
-
-    /**
-     * Clear the map.
-     */
-    @Override
-    public void clear() {
-        super.clear();
-        mapCleaner.clear();
-    }
-
-    /**
-     *
-     * @return Maximum number of items in the map.
-     */
-    public long getMaxSize() {
-        return maxSize;
-    }
-
-    /**
-     * Maximum number of items in the map.<br>
-     * Capacity will not be reduced.
-     *
-     * @param maxSize
-     */
-    public final void setMaxSize(long maxSize) {
-        this.maxSize = maxSize > UNLIMITED_MAP ? maxSize : Long.MAX_VALUE;
-    }
-
-    /**
-     *
-     * @return Frequency that items are checked for removal from map.
-     */
-    public long getCleanerInterval() {
-        return cleanerInterval;
-    }
-
-    /**
-     * Frequency that items are checked for removal from map.
-     *
-     * @param cleanerInterval Milliseconds
-     */
-    public final void setCleanerInterval(long cleanerInterval) {
-
-        boolean isChanged = applyCleanerInterval(cleanerInterval);
-
-        //Reset the expiry if running and changed.
-        if (running && isChanged) {
-            startExpiry();
-        }
-    }
-
-    private boolean applyCleanerInterval(long cleanerInterval) {
-        long originalCleanerInterval = this.cleanerInterval;
-        if (MINIMUM_MAP_CLEANER_INTERVAL < cleanerInterval) {
-            this.cleanerInterval = cleanerInterval;
-        } else {
-            LOGGER.warn("Cleaner Interval: {} less than minimum: {}. Setting 
to minimum.", cleanerInterval, MINIMUM_MAP_CLEANER_INTERVAL);
-            this.cleanerInterval = MINIMUM_MAP_CLEANER_INTERVAL;
-        }
-        return originalCleanerInterval != this.cleanerInterval;
-    }
-
-    /**
-     *
-     * @return Duration that items remain in map.
-     */
-    public long getExpiryInterval() {
-        return expiryInterval;
-    }
-
-    /**
-     * Duration that items remain in map.<br>
-     * Items will not be removed until next cleaner interval.
-     *
-     * @param expiryInterval Milliseconds
-     */
-    public final void setExpiryInterval(long expiryInterval) {
-
-        this.expiring = expiryInterval > UNLIMITED_EXPIRY;
-
-        long minimum_interval = cleanerInterval + 1;
-        if (expiryInterval < minimum_interval) {
-            if (this.expiring) {
-                //Ensure that the expiry interval is greater than the cleaner 
interval and warn that value has been changed.
-                LOGGER.warn("Expiry Interval: {} cannot be less than Cleaner 
Interval: {}. Setting to Minimum Interval: {}", expiryInterval, 
cleanerInterval, minimum_interval);
-            }
-            this.expiryInterval = minimum_interval;
-        } else {
-            this.expiryInterval = expiryInterval;
-        }
-
-        if (this.mapCleaner == null) {
-            this.mapCleaner = new ExpiringMapCleaner(this, expiryInterval);
-        } else {
-            this.mapCleaner.setExpiryInterval(this.expiryInterval);
-        }
-    }
-
-    /**
-     *
-     * @return Delay between warnings the map is full.
-     */
-    public long getFullMapWarningInterval() {
-        return fullMapWarningInterval;
-    }
-
-    /**
-     * Delay between warnings the map is full.
-     *
-     * @param fullMapWarningInterval Milliseconds
-     */
-    public void setFullMapWarningInterval(long fullMapWarningInterval) {
-        this.fullMapWarningInterval = fullMapWarningInterval;
-    }
-
-    /**
-     *
-     * @return Label of the Expiring Map.
-     */
-    public String getLabel() {
-        return label;
-    }
-
-    /**
-     * Set the label of the Expiring Map.
-     *
-     * @param label
-     */
-    public void setLabel(String label) {
-        this.label = label;
-    }
-
-    /**
-     * Start expiring items from the map.
-     */
-    public void startExpiry() {
-        startExpiry(cleanerInterval);
-    }
-
-    /**
-     * Start expiring items from the map with adjusted cleaner interval.
-     *
-     * @param cleanerInterval Milliseconds between checks for expiry.
-     */
-    public void startExpiry(long cleanerInterval) {
-        stopExpiry();
-        if (expiring) {
-            applyCleanerInterval(cleanerInterval);
-            cleanerTimer = new Timer(label, true);
-            mapCleaner = new ExpiringMapCleaner(mapCleaner);
-            cleanerTimer.scheduleAtFixedRate(mapCleaner, this.cleanerInterval, 
this.cleanerInterval);
-        }
-
-        running = true;
-    }
-
-    /**
-     * Stop expiring items from the map.
-     */
-    public void stopExpiry() {
-        if (cleanerTimer != null) {
-            cleanerTimer.cancel();
-            cleanerTimer = null;
-        }
-
-        running = false;
-    }
-
-    /**
-     *
-     * @return True if the Expiring Map is running.
-     */
-    public boolean isRunning() {
-        return running;
-    }
-
-    /**
-     *
-     * @return True if the Expiring Map will remove items.
-     */
-    public boolean isExpiring() {
-        return expiring;
-    }
-
-    @Override
-    public String toString() {
-        return "ExpiringMap{" + "label=" + label + ", running=" + running + ", 
expiring=" + expiring + ", maxSize=" + maxSize + ", expiryInterval=" + 
expiryInterval + ", cleanerInterval=" + cleanerInterval + ", 
fullMapWarningInterval=" + fullMapWarningInterval + ", fullMapWarning=" + 
fullMapWarning + ", mapCleaner=" + mapCleaner + ", cleanerTimer=" + 
cleanerTimer + '}';
-    }
-
-}
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMap2.java
 
b/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMap2.java
deleted file mode 100644
index b119f5f00a..0000000000
--- 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMap2.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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 org.apache.jena.ext.io.github.galbiston.expiring_map;
-
-import java.util.AbstractMap;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-import com.github.benmanes.caffeine.cache.Cache;
-import com.github.benmanes.caffeine.cache.Caffeine;
-
-public class ExpiringMap2<K,V> extends AbstractMap<K,V> {
-
-    private Cache<K,V> cache;
-
-    ExpiringMap2(int size) {
-        @SuppressWarnings("unchecked")
-        Caffeine<K,V> builder = (Caffeine<K,V>)Caffeine.newBuilder()
-                .maximumSize(size)
-                .executor(c->c.run())
-                .expireAfterAccess(5000, TimeUnit.MILLISECONDS)
-                ;
-        Cache<K,V> cache = builder.build();
-    }
-
-    @Override
-    public Set<Entry<K, V>> entrySet() {
-        return null;
-    }
-}
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMapCleaner.java
 
b/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMapCleaner.java
deleted file mode 100644
index 7b1c5e967d..0000000000
--- 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMapCleaner.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2018 the original author or authors.
- * See the notice.md file distributed with this work for additional
- * information regarding copyright ownership.
- *
- * Licensed 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 org.apache.jena.ext.io.github.galbiston.expiring_map;
-
-import java.util.Collections;
-import java.util.SortedSet;
-import java.util.TimerTask;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- *
- *
- */
-public class ExpiringMapCleaner extends TimerTask {
-
-    //private static final Logger LOGGER = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-    private final SortedSet<KeyTimestampPair> tracking = 
Collections.synchronizedSortedSet(new TreeSet<>());
-    private final ConcurrentHashMap<Object, Long> refresh = new 
ConcurrentHashMap<>();
-    private final ExpiringMap<? , ? > map;
-    private long expiryInterval;
-
-    public ExpiringMapCleaner(ExpiringMap<?,?> map, long expiryInterval) {
-        this.map = map;
-        this.expiryInterval = expiryInterval;
-    }
-
-    public ExpiringMapCleaner(ExpiringMapCleaner mapCleaner) {
-        this.map = mapCleaner.map;
-        this.expiryInterval = mapCleaner.expiryInterval;
-        tracking.addAll(mapCleaner.tracking);
-        refresh.putAll(mapCleaner.refresh);
-    }
-
-    @Override
-    public void run() {
-
-        //LOGGER.info("Run Start - Tracker: {}, Refresh: {}, Map: {}", 
tracking.size(), refresh.size(), map.size());
-        long thresholdTimestamp = System.currentTimeMillis() - expiryInterval;
-        boolean isEarlier = true;
-        while (isEarlier) {
-            if (tracking.isEmpty()) {
-                return;
-            }
-
-            KeyTimestampPair current = tracking.first();
-            isEarlier = current.isEarlier(thresholdTimestamp);
-            if (isEarlier) {
-                Object key = current.getKey();
-                tracking.remove(current);
-                if (refresh.containsKey(key)) {
-                    //Check whether the refresh is still valid.
-                    Long timestamp = refresh.get(key);
-                    if (thresholdTimestamp < timestamp) {
-                        tracking.add(new KeyTimestampPair(key, timestamp));
-                    }
-                    refresh.remove(key);
-                } else {
-                    map.remove(key);
-                }
-
-            }
-        }
-        //LOGGER.info("Run End - Tracker: {}, Refresh: {}, Map: {}", 
tracking.size(), refresh.size(), map.size());
-    }
-
-    public synchronized void refresh(Object key) {
-        refresh.put(key, System.currentTimeMillis());
-    }
-
-    public synchronized void put(Object key) {
-        tracking.add(new KeyTimestampPair(key, System.currentTimeMillis()));
-    }
-
-    public synchronized void setExpiryInterval(long expiryInterval) {
-        this.expiryInterval = expiryInterval;
-    }
-
-    public synchronized void clear() {
-        tracking.clear();
-    }
-
-}
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMaps.java
 
b/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMaps.java
deleted file mode 100644
index 69a07668d6..0000000000
--- 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMaps.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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 org.apache.jena.ext.io.github.galbiston.expiring_map;
-
-public class ExpiringMaps {
-
-    public static <K,V> ExpiringMap<K,V> newExpiringMap(String label, int 
maxSize, long expiryInterval) {
-        return new ExpiringMap<>(label, maxSize, expiryInterval);
-    }
-
-
-}
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/KeyTimestampPair.java
 
b/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/KeyTimestampPair.java
deleted file mode 100644
index 13e8ae3e8d..0000000000
--- 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/KeyTimestampPair.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2018 the original author or authors.
- * See the notice.md file distributed with this work for additional
- * information regarding copyright ownership.
- *
- * Licensed 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 org.apache.jena.ext.io.github.galbiston.expiring_map;
-
-import java.util.Objects;
-
-/**
- *
- *
- */
-public class KeyTimestampPair implements Comparable<KeyTimestampPair> {
-
-    private final Object key;
-    private long timestamp;
-
-    public KeyTimestampPair(Object key, long timestamp) {
-        this.key = key;
-        this.timestamp = timestamp;
-    }
-
-    public boolean hasKey(Object key) {
-        return this.key.equals(key);
-    }
-
-    public Object getKey() {
-        return key;
-    }
-
-    public long getTimestamp() {
-        return timestamp;
-    }
-
-    public boolean isEarlier(long timestamp) {
-        return this.timestamp < timestamp;
-    }
-
-    public void setTimestamp(long timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    @Override
-    public int compareTo(KeyTimestampPair o) {
-
-        if (o == null) {
-            throw new NullPointerException();
-        }
-
-        if (timestamp < o.timestamp) {
-            return -1;
-        } else if (timestamp > o.timestamp) {
-            return 1;
-        } else {
-            if (key.equals(o.key)) {
-                return 0;
-            } else {
-                return -1;
-            }
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 7;
-        hash = 67 * hash + Objects.hashCode(this.key);
-        hash = 67 * hash + (int) (this.timestamp ^ (this.timestamp >>> 32));
-        return hash;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final KeyTimestampPair other = (KeyTimestampPair) obj;
-        if (this.timestamp != other.timestamp) {
-            return false;
-        }
-        return Objects.equals(this.key, other.key);
-    }
-
-    @Override
-    public String toString() {
-        return "KeyTimestampPair{" + "key=" + key + ", timestamp=" + timestamp 
+ '}';
-    }
-}
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/MapDefaultValues.java
 
b/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/MapDefaultValues.java
deleted file mode 100644
index a91695db0d..0000000000
--- 
a/jena-geosparql/src/main/java/org/apache/jena/ext/io/github/galbiston/expiring_map/MapDefaultValues.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2018 the original author or authors.
- * See the notice.md file distributed with this work for additional
- * information regarding copyright ownership.
- *
- * Licensed 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 org.apache.jena.ext.io.github.galbiston.expiring_map;
-
-/**
- *
- *
- */
-public interface MapDefaultValues {
-
-    public static final int UNLIMITED_MAP = -1;
-    public static final long UNLIMITED_EXPIRY = 0;
-
-    public static final int NO_MAP = 0;
-    public static final long MAP_EXPIRY_INTERVAL = 5000l;
-    public static final long MAP_CLEANER_INTERVAL = 1000l;
-    public static final long FULL_MAP_WARNING_INTERVAL = 30000l;
-    public static final long MINIMUM_MAP_CLEANER_INTERVAL = 100l;
-    public static final int UNLIMITED_INITIAL_CAPACITY = 50000;
-}
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/configuration/GeoSPARQLConfig.java
 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/configuration/GeoSPARQLConfig.java
index 5d966059f8..759e5f11f2 100644
--- 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/configuration/GeoSPARQLConfig.java
+++ 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/configuration/GeoSPARQLConfig.java
@@ -22,6 +22,8 @@ import java.io.File;
 import org.apache.jena.geosparql.geof.topological.RelateFF;
 import org.apache.jena.geosparql.implementation.datatype.GeometryDatatype;
 import org.apache.jena.geosparql.implementation.function_registration.*;
+import org.apache.jena.geosparql.implementation.index.GeometryLiteralIndex;
+import org.apache.jena.geosparql.implementation.index.GeometryTransformIndex;
 import org.apache.jena.geosparql.implementation.index.IndexConfiguration;
 import 
org.apache.jena.geosparql.implementation.index.IndexConfiguration.IndexOption;
 import org.apache.jena.geosparql.implementation.index.QueryRewriteIndex;
@@ -92,38 +94,6 @@ public class GeoSPARQLConfig {
         setup(IndexOption.MEMORY, isQueryRewriteEnabled);
     }
 
-    /**
-     * Initialise all GeoSPARQL property and filter functions with memory
-     * indexing.
-     * <br>Use this for in-memory indexing GeoSPARQL setup and to control the
-     * index sizes. Expiry is defaulted to 5,000 milliseconds.
-     * <br>This does not affect the use of Spatial Indexes for Datasets.
-     *
-     * @param geometryLiteralIndex
-     * @param geometryTransformIndex
-     * @param queryRewriteIndex
-     */
-    public static final void setupMemoryIndexSize(Integer 
geometryLiteralIndex, Integer geometryTransformIndex, Integer 
queryRewriteIndex) {
-        setup(IndexOption.MEMORY, true);
-        IndexConfiguration.setIndexMaxSize(geometryLiteralIndex, 
geometryTransformIndex, queryRewriteIndex);
-    }
-
-    /**
-     * Initialise all GeoSPARQL property and filter functions with memory
-     * indexing.
-     * <br>Use this for in-memory indexing GeoSPARQL setup and to control the
-     * index expiry rate (milliseconds). Size is defaulted to unlimited.
-     * <br>This does not affect the use of Spatial Indexes for Datasets.
-     *
-     * @param geometryLiteralIndex
-     * @param geometryTransformIndex
-     * @param queryRewriteIndex
-     */
-    public static final void setupMemoryIndexExpiry(Long geometryLiteralIndex, 
Long geometryTransformIndex, Long queryRewriteIndex) {
-        setup(IndexOption.MEMORY, true);
-        IndexConfiguration.setIndexExpiry(geometryLiteralIndex, 
geometryTransformIndex, queryRewriteIndex);
-    }
-
     /**
      * Initialise all GeoSPARQL property and filter functions with memory
      * indexing.
@@ -142,8 +112,10 @@ public class GeoSPARQLConfig {
      */
     public static final void setupMemoryIndex(Integer geometryLiteralIndex, 
Integer geometryTransformIndex, Integer queryRewriteIndex, Long 
geometryLiteralIndexExpiry, Long geometryTransformIndexExpiry, Long 
queryRewriteIndexExpiry, Boolean isQueryRewriteEnabled) {
         setup(IndexOption.MEMORY, isQueryRewriteEnabled);
-        IndexConfiguration.setIndexMaxSize(geometryLiteralIndex, 
geometryTransformIndex, queryRewriteIndex);
-        IndexConfiguration.setIndexExpiry(geometryLiteralIndexExpiry, 
geometryTransformIndexExpiry, queryRewriteIndexExpiry);
+        GeometryLiteralIndex.reset(geometryLiteralIndex, 
geometryLiteralIndexExpiry);
+        GeometryTransformIndex.reset(geometryTransformIndex, 
geometryTransformIndexExpiry);
+        QueryRewriteIndex.setMaxSize(queryRewriteIndex);
+        QueryRewriteIndex.setExpiry(queryRewriteIndexExpiry);
     }
 
     /**
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/CacheConfiguration.java
 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/CacheConfiguration.java
new file mode 100644
index 0000000000..f71024ddb2
--- /dev/null
+++ 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/CacheConfiguration.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2018 the original author or authors.
+ * See the notice.md file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * Licensed 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 org.apache.jena.geosparql.implementation.index;
+
+import com.github.benmanes.caffeine.cache.Caffeine;
+import org.apache.jena.atlas.lib.Cache;
+import org.apache.jena.atlas.lib.CacheFactory;
+import org.apache.jena.atlas.lib.cache.CacheCaffeine;
+
+import java.time.Duration;
+
+/**
+ *
+ */
+public class CacheConfiguration {
+
+    public static final int UNLIMITED_MAP = -1;
+    public static final int NO_MAP = 0;
+    public static final long MAP_EXPIRY_INTERVAL = 5000l;
+    public static final int UNLIMITED_INITIAL_CAPACITY = 50000;
+
+    private CacheConfiguration() {
+    }
+
+    /**
+     * Creates a cache
+     *
+     * @param maxSize            Maximum size, use {@value #NO_MAP} to disable 
caching, or {@value #UNLIMITED_MAP} to
+     *                           have an unlimited cache size
+     * @param expiryMilliseconds Expiry duration in milliseconds, entries 
which have not been accessed within this
+     *                           interval will be automatically expired from 
the cache
+     */
+    public static <K, V> Cache<K, V> create(long maxSize, long 
expiryMilliseconds) {
+        if (maxSize == NO_MAP) {
+            return CacheFactory.createNullCache();
+        }
+
+        long actualMaxSize = maxSize > UNLIMITED_MAP ? maxSize : 
Long.MAX_VALUE;
+        int actualInitialCapacity =
+                actualMaxSize == Long.MAX_VALUE ? UNLIMITED_INITIAL_CAPACITY : 
(int) actualMaxSize / 4;
+        return new CacheCaffeine<>(expiryMilliseconds > 0 ? 
Caffeine.newBuilder()
+                                                                    
.maximumSize(actualMaxSize)
+                                                                    
.initialCapacity(actualInitialCapacity)
+                                                                    
.expireAfterAccess(
+                                                                            
Duration.ofMillis(expiryMilliseconds))
+                                                                    .build() :
+                                   Caffeine.newBuilder()
+                                           .maximumSize(actualMaxSize)
+                                           
.initialCapacity(actualInitialCapacity)
+                                           .build());
+    }
+}
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/GeometryLiteralIndex.java
 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/GeometryLiteralIndex.java
index 05c72cd173..3d11f83012 100644
--- 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/GeometryLiteralIndex.java
+++ 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/GeometryLiteralIndex.java
@@ -17,13 +17,10 @@
  */
 package org.apache.jena.geosparql.implementation.index;
 
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.MAP_EXPIRY_INTERVAL;
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.UNLIMITED_MAP;
+import static 
org.apache.jena.geosparql.implementation.index.CacheConfiguration.MAP_EXPIRY_INTERVAL;
+import static 
org.apache.jena.geosparql.implementation.index.CacheConfiguration.UNLIMITED_MAP;
 
-import java.util.Map;
-
-import org.apache.jena.ext.io.github.galbiston.expiring_map.ExpiringMap;
-import org.apache.jena.ext.io.github.galbiston.expiring_map.ExpiringMaps;
+import org.apache.jena.atlas.lib.Cache;
 import org.apache.jena.geosparql.implementation.GeometryWrapper;
 import org.apache.jena.geosparql.implementation.datatype.GeometryDatatype;
 
@@ -34,10 +31,9 @@ import 
org.apache.jena.geosparql.implementation.datatype.GeometryDatatype;
 public class GeometryLiteralIndex {
 
     private static boolean INDEX_ACTIVE = false;
-    private static final String PRIMARY_INDEX_LABEL = "Primary Geometry 
Literal Index";
-    private static final String SECONDARY_INDEX_LABEL = "Secondary Geometry 
Literal Index";
-    private static ExpiringMap<String, GeometryWrapper> PRIMARY_INDEX = 
ExpiringMaps.newExpiringMap(PRIMARY_INDEX_LABEL, UNLIMITED_MAP, 
MAP_EXPIRY_INTERVAL);
-    private static ExpiringMap<String, GeometryWrapper> SECONDARY_INDEX = 
ExpiringMaps.newExpiringMap(SECONDARY_INDEX_LABEL, UNLIMITED_MAP, 
MAP_EXPIRY_INTERVAL);
+    private static Cache<String, GeometryWrapper>
+            PRIMARY_INDEX = CacheConfiguration.create(UNLIMITED_MAP, 
MAP_EXPIRY_INTERVAL);
+    private static Cache<String, GeometryWrapper> SECONDARY_INDEX = 
CacheConfiguration.create(UNLIMITED_MAP, MAP_EXPIRY_INTERVAL);
 
     public enum GeometryIndex {
         PRIMARY, SECONDARY
@@ -57,15 +53,15 @@ public class GeometryLiteralIndex {
         return geometryWrapper;
     }
 
-    private static GeometryWrapper retrieveMemoryIndex(String geometryLiteral, 
GeometryDatatype geometryDatatype, Map<String, GeometryWrapper> index, 
Map<String, GeometryWrapper> otherIndex) {
+    private static GeometryWrapper retrieveMemoryIndex(String geometryLiteral, 
GeometryDatatype geometryDatatype, Cache<String, GeometryWrapper> index, 
Cache<String, GeometryWrapper> otherIndex) {
 
         GeometryWrapper geometryWrapper;
 
         if (INDEX_ACTIVE) {
 
-            geometryWrapper = index.get(geometryLiteral);
+            geometryWrapper = index.getIfPresent(geometryLiteral);
             if (geometryWrapper == null) {
-                geometryWrapper = otherIndex.get(geometryLiteral);
+                geometryWrapper = otherIndex.getIfPresent(geometryLiteral);
                 if (geometryWrapper == null) {
                     geometryWrapper = geometryDatatype.read(geometryLiteral);
                 }
@@ -87,33 +83,12 @@ public class GeometryLiteralIndex {
         SECONDARY_INDEX.clear();
     }
 
-    /**
-     * Sets the maximum size of Geometry Literal Index.
-     *
-     * @param maxSize : use -1 for unlimited size
-     */
-    public static final void setMaxSize(int maxSize) {
-        PRIMARY_INDEX.setMaxSize(maxSize);
-        SECONDARY_INDEX.setMaxSize(maxSize);
-    }
-
-    /**
-     * Sets the expiry time in milliseconds of the Geometry Literal Indexes, if
-     * active.
-     *
-     * @param expiryInterval : use 0 or negative for unlimited timeout
-     */
-    public static final void setExpiry(long expiryInterval) {
-        PRIMARY_INDEX.setExpiryInterval(expiryInterval);
-        SECONDARY_INDEX.setExpiryInterval(expiryInterval);
-    }
-
     /**
      *
      * @return Number of items in the primary index.
      */
     public static final long getPrimaryIndexSize() {
-        return PRIMARY_INDEX.mappingCount();
+        return PRIMARY_INDEX.size();
     }
 
     /**
@@ -121,7 +96,7 @@ public class GeometryLiteralIndex {
      * @return Number of items in the secondary index.
      */
     public static final long getSecondaryIndexSize() {
-        return SECONDARY_INDEX.mappingCount();
+        return SECONDARY_INDEX.size();
     }
 
     /**
@@ -139,13 +114,6 @@ public class GeometryLiteralIndex {
      */
     public static void setIndexActive(boolean indexActive) {
         INDEX_ACTIVE = indexActive;
-        if (INDEX_ACTIVE) {
-            PRIMARY_INDEX.startExpiry();
-            SECONDARY_INDEX.startExpiry();
-        } else {
-            PRIMARY_INDEX.stopExpiry();
-            SECONDARY_INDEX.stopExpiry();
-        }
     }
 
     /**
@@ -156,8 +124,8 @@ public class GeometryLiteralIndex {
      * @param expiryInterval
      */
     public static void reset(int maxSize, long expiryInterval) {
-        PRIMARY_INDEX = ExpiringMaps.newExpiringMap(PRIMARY_INDEX_LABEL, 
maxSize, expiryInterval);
-        SECONDARY_INDEX = ExpiringMaps.newExpiringMap(SECONDARY_INDEX_LABEL, 
maxSize, expiryInterval);
+        PRIMARY_INDEX = CacheConfiguration.create(maxSize, expiryInterval);
+        SECONDARY_INDEX = CacheConfiguration.create(maxSize, expiryInterval);
     }
 
 }
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/GeometryTransformIndex.java
 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/GeometryTransformIndex.java
index 7115e18a47..fd19d64dbc 100644
--- 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/GeometryTransformIndex.java
+++ 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/GeometryTransformIndex.java
@@ -17,13 +17,12 @@
  */
 package org.apache.jena.geosparql.implementation.index;
 
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.MAP_EXPIRY_INTERVAL;
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.UNLIMITED_MAP;
+import static 
org.apache.jena.geosparql.implementation.index.CacheConfiguration.MAP_EXPIRY_INTERVAL;
+import static 
org.apache.jena.geosparql.implementation.index.CacheConfiguration.UNLIMITED_MAP;
 
 import java.util.Objects;
 
-import org.apache.jena.ext.io.github.galbiston.expiring_map.ExpiringMap;
-import org.apache.jena.ext.io.github.galbiston.expiring_map.ExpiringMaps;
+import org.apache.jena.atlas.lib.Cache;
 import org.apache.jena.geosparql.implementation.DimensionInfo;
 import org.apache.jena.geosparql.implementation.GeometryWrapper;
 import org.apache.jena.geosparql.implementation.jts.GeometryTransformation;
@@ -43,8 +42,8 @@ import org.opengis.util.FactoryException;
 public class GeometryTransformIndex {
 
     private static boolean INDEX_ACTIVE = false;
-    private static final String GEOMETRY_TRANSFORM_LABEL = "Geometry 
Transform";
-    private static ExpiringMap<IndexKey, GeometryWrapper> 
GEOMETRY_TRANSFORM_INDEX = 
ExpiringMaps.newExpiringMap(GEOMETRY_TRANSFORM_LABEL, UNLIMITED_MAP, 
MAP_EXPIRY_INTERVAL);
+    private static Cache<IndexKey, GeometryWrapper>
+            GEOMETRY_TRANSFORM_INDEX = 
CacheConfiguration.create(UNLIMITED_MAP, MAP_EXPIRY_INTERVAL);
 
     /**
      *
@@ -62,7 +61,7 @@ public class GeometryTransformIndex {
 
         if (INDEX_ACTIVE && storeSRSTransform) {
 
-            transformedGeometryWrapper = GEOMETRY_TRANSFORM_INDEX.get(key);
+            transformedGeometryWrapper = 
GEOMETRY_TRANSFORM_INDEX.getIfPresent(key);
             if (transformedGeometryWrapper == null) {
                 transformedGeometryWrapper = transform(sourceGeometryWrapper, 
srsURI);
                 GEOMETRY_TRANSFORM_INDEX.put(key, transformedGeometryWrapper);
@@ -97,31 +96,12 @@ public class GeometryTransformIndex {
         GEOMETRY_TRANSFORM_INDEX.clear();
     }
 
-    /**
-     * Sets whether the maximum size of the Geometry Transform Index.
-     *
-     * @param maxSize : use -1 for unlimited size
-     */
-    public static final void setMaxSize(int maxSize) {
-        GEOMETRY_TRANSFORM_INDEX.setMaxSize(maxSize);
-    }
-
-    /**
-     * Sets the expiry time in milliseconds of the Geometry Transform Index, if
-     * active.
-     *
-     * @param expiryInterval : use 0 or negative for unlimited timeout
-     */
-    public static final void setExpiry(long expiryInterval) {
-        GEOMETRY_TRANSFORM_INDEX.setExpiryInterval(expiryInterval);
-    }
-
     /**
      *
      * @return Number of items in the index.
      */
     public static final long getGeometryTransformIndexSize() {
-        return GEOMETRY_TRANSFORM_INDEX.mappingCount();
+        return GEOMETRY_TRANSFORM_INDEX.size();
     }
 
     /**
@@ -139,11 +119,6 @@ public class GeometryTransformIndex {
      */
     public static void setIndexActive(boolean indexActive) {
         INDEX_ACTIVE = indexActive;
-        if (INDEX_ACTIVE) {
-            GEOMETRY_TRANSFORM_INDEX.startExpiry();
-        } else {
-            GEOMETRY_TRANSFORM_INDEX.stopExpiry();
-        }
     }
 
     /**
@@ -154,7 +129,7 @@ public class GeometryTransformIndex {
      * @param expiryInterval
      */
     public static void reset(int maxSize, long expiryInterval) {
-        GEOMETRY_TRANSFORM_INDEX = 
ExpiringMaps.newExpiringMap(GEOMETRY_TRANSFORM_LABEL, maxSize, expiryInterval);
+        GEOMETRY_TRANSFORM_INDEX = CacheConfiguration.create(maxSize, 
expiryInterval);
     }
 
     private static class IndexKey {
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/IndexConfiguration.java
 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/IndexConfiguration.java
index ce905c639f..19617a0b3b 100644
--- 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/IndexConfiguration.java
+++ 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/IndexConfiguration.java
@@ -17,10 +17,11 @@
  */
 package org.apache.jena.geosparql.implementation.index;
 
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.NO_MAP;
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.UNLIMITED_MAP;
+import static 
org.apache.jena.geosparql.implementation.index.CacheConfiguration.NO_MAP;
+import static 
org.apache.jena.geosparql.implementation.index.CacheConfiguration.UNLIMITED_MAP;
 
 import java.util.UUID;
+
 import org.apache.jena.geosparql.implementation.registry.MathTransformRegistry;
 import org.apache.jena.geosparql.implementation.registry.SRSRegistry;
 
@@ -57,8 +58,8 @@ public class IndexConfiguration {
     private static void setupNoIndex() {
         IndexConfiguration.resetIndexes();
         IndexConfiguration.stopIndexes();
-        GeometryLiteralIndex.setMaxSize(NO_MAP);
-        GeometryTransformIndex.setMaxSize(NO_MAP);
+        GeometryLiteralIndex.reset(NO_MAP, 0);
+        GeometryTransformIndex.reset(NO_MAP, 0);
         QueryRewriteIndex.setMaxSize(NO_MAP);
     }
 
@@ -66,8 +67,8 @@ public class IndexConfiguration {
      * Indexes are set to unlimited storage and started.
      */
     private static void setupMemoryIndex() {
-        GeometryLiteralIndex.setMaxSize(UNLIMITED_MAP);
-        GeometryTransformIndex.setMaxSize(UNLIMITED_MAP);
+        GeometryLiteralIndex.reset(UNLIMITED_MAP, 0);
+        GeometryTransformIndex.reset(UNLIMITED_MAP, 0);
         QueryRewriteIndex.setMaxSize(UNLIMITED_MAP);
         IndexConfiguration.startIndexes();
     }
@@ -90,33 +91,6 @@ public class IndexConfiguration {
         //QueryRewriteIndex are on a Dataset basis.
     }
 
-    /**
-     * Set the maximum size of the indexes.<br>
-     * Zero for no index and -1 for unlimited size.
-     *
-     * @param geometryLiteralIndex
-     * @param geometryTransformIndex
-     * @param queryRewriteIndex
-     */
-    public static final void setIndexMaxSize(int geometryLiteralIndex, int 
geometryTransformIndex, int queryRewriteIndex) {
-        GeometryLiteralIndex.setMaxSize(geometryLiteralIndex);
-        GeometryTransformIndex.setMaxSize(geometryTransformIndex);
-        QueryRewriteIndex.setMaxSize(queryRewriteIndex);
-    }
-
-    /**
-     * Set the index expiry interval in milliseconds.
-     *
-     * @param geometryLiteralIndex
-     * @param geometryTransformIndex
-     * @param queryRewriteIndex
-     */
-    public static final void setIndexExpiry(long geometryLiteralIndex, long 
geometryTransformIndex, long queryRewriteIndex) {
-        GeometryLiteralIndex.setExpiry(geometryLiteralIndex);
-        GeometryTransformIndex.setExpiry(geometryTransformIndex);
-        QueryRewriteIndex.setExpiry(queryRewriteIndex);
-    }
-
     public static final void resetIndexes() {
         GeometryLiteralIndex.clear();
         GeometryTransformIndex.clear();
diff --git 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/QueryRewriteIndex.java
 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/QueryRewriteIndex.java
index 56c4fac2a1..6045174e65 100644
--- 
a/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/QueryRewriteIndex.java
+++ 
b/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/index/QueryRewriteIndex.java
@@ -17,11 +17,7 @@
  */
 package org.apache.jena.geosparql.implementation.index;
 
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.MAP_EXPIRY_INTERVAL;
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.UNLIMITED_MAP;
-
-import org.apache.jena.ext.io.github.galbiston.expiring_map.ExpiringMap;
-import org.apache.jena.ext.io.github.galbiston.expiring_map.ExpiringMaps;
+import org.apache.jena.atlas.lib.Cache;
 import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
 import org.apache.jena.geosparql.geo.topological.GenericPropertyFunction;
 import org.apache.jena.graph.Graph;
@@ -36,34 +32,31 @@ import org.apache.jena.sparql.graph.GraphFactory;
 import org.apache.jena.sparql.util.Context;
 import org.apache.jena.sparql.util.Symbol;
 
+import java.util.Iterator;
+
+import static 
org.apache.jena.geosparql.implementation.index.CacheConfiguration.MAP_EXPIRY_INTERVAL;
+import static 
org.apache.jena.geosparql.implementation.index.CacheConfiguration.UNLIMITED_MAP;
+
 /**
  *
  */
 public class QueryRewriteIndex {
 
     private boolean indexActive;
-    private final String queryRewriteLabel;
-    private ExpiringMap<Triple, Boolean> index;
-    private static String LABEL_DEFAULT = "Query Rewrite";
+    private Cache<Triple, Boolean> index;
     private static int MAP_SIZE_DEFAULT = UNLIMITED_MAP;
     private static long MAP_EXPIRY_INTERVAL_DEFAULT = MAP_EXPIRY_INTERVAL;
 
     public static final Symbol QUERY_REWRITE_INDEX_SYMBOL = 
Symbol.create("http://jena.apache.org/spatial#query-index";);
 
     public QueryRewriteIndex() {
-        this.queryRewriteLabel = LABEL_DEFAULT;
         this.indexActive = GeoSPARQLConfig.isQueryRewriteEnabled();
-        this.index = ExpiringMaps.newExpiringMap(queryRewriteLabel, 
MAP_SIZE_DEFAULT, MAP_EXPIRY_INTERVAL_DEFAULT);
-        if (indexActive) {
-            index.startExpiry();
-        }
+        this.index = CacheConfiguration.create(MAP_SIZE_DEFAULT, 
MAP_EXPIRY_INTERVAL_DEFAULT);
     }
 
     public QueryRewriteIndex(String queryRewriteLabel, int maxSize, long 
expiryInterval) {
-        this.queryRewriteLabel = queryRewriteLabel;
         this.indexActive = true;
-        this.index = ExpiringMaps.newExpiringMap(queryRewriteLabel, maxSize, 
expiryInterval);
-        this.index.startExpiry();
+        this.index = CacheConfiguration.create(maxSize, expiryInterval);
     }
 
     /**
@@ -83,7 +76,7 @@ public class QueryRewriteIndex {
         if (indexActive) {
             Triple key = Triple.create(subjectGeometryLiteral, predicate, 
objectGeometryLiteral);
             try {
-                return index.computeIfAbsent(key, k -> 
propertyFunction.testFilterFunction(subjectGeometryLiteral, 
objectGeometryLiteral));
+                return index.get(key, k -> 
propertyFunction.testFilterFunction(subjectGeometryLiteral, 
objectGeometryLiteral));
             } catch (NullPointerException ex) {
                 //Catch NullPointerException and fall through to default 
action.
             }
@@ -99,26 +92,6 @@ public class QueryRewriteIndex {
         index.clear();
     }
 
-    /**
-     * Sets whether the Query Rewrite Index is active.
-     * <br> The index will be empty after this process.
-     *
-     * @param maxSize : use -1 for unlimited size
-     */
-    public final void setMapSize(int maxSize) {
-        index.setMaxSize(maxSize);
-    }
-
-    /**
-     * Sets the expiry time in milliseconds of the Query Rewrite Index, if
-     * active.
-     *
-     * @param expiryInterval : use 0 or negative for unlimited timeout
-     */
-    public final void setMapExpiry(long expiryInterval) {
-        index.setExpiryInterval(expiryInterval);
-    }
-
     /**
      *
      * @return True if index is active.
@@ -128,17 +101,19 @@ public class QueryRewriteIndex {
     }
 
     /**
-     * COnverts the index to a model of asserted spatial relation statements.
+     * Converts the index to a model of asserted spatial relation statements.
      *
      * @return Model containing all true assertions.
      */
     public Model toModel() {
         Graph graph = GraphFactory.createDefaultGraph();
-        index.forEach((key, value) -> {
-            if (value) {
+        for (Iterator<Triple> it = index.keys(); it.hasNext(); ) {
+            Triple key = it.next();
+            Boolean value = index.getIfPresent(key);
+            if (value != null && value) {
                 graph.add(key);
             }
-        });
+        }
         return ModelFactory.createModelForGraph(graph);
     }
 
@@ -149,12 +124,6 @@ public class QueryRewriteIndex {
      */
     public final void setActive(boolean indexActive) {
         this.indexActive = indexActive;
-
-        if (indexActive) {
-            index.startExpiry();
-        } else {
-            index.stopExpiry();
-        }
     }
 
     /**
@@ -162,18 +131,18 @@ public class QueryRewriteIndex {
      * @return Number of items in the index.
      */
     public final long getIndexSize() {
-        return index.mappingCount();
+        return index.size();
     }
 
     /**
      * Reset the index to the provided max size and expiry interval.<br>
      * All contents will be lost.
      *
-     * @param maxSize
-     * @param expiryInterval
+     * @param maxSize Maximum size
+     * @param expiryInterval Expiry interval
      */
     public void reset(int maxSize, long expiryInterval) {
-        index = ExpiringMaps.newExpiringMap(queryRewriteLabel, maxSize, 
expiryInterval);
+        index = CacheConfiguration.create(maxSize, expiryInterval);
     }
 
     /**
@@ -262,7 +231,7 @@ public class QueryRewriteIndex {
      * @return QueryRewriteIndex contained in the Context.
      */
     public static final QueryRewriteIndex retrieve(Context context) {
-        QueryRewriteIndex queryRewriteIndex = (QueryRewriteIndex) 
context.get(QUERY_REWRITE_INDEX_SYMBOL, null);
+        QueryRewriteIndex queryRewriteIndex = 
context.get(QUERY_REWRITE_INDEX_SYMBOL, null);
 
         if (queryRewriteIndex == null) {
             queryRewriteIndex = createDefault();
diff --git 
a/jena-geosparql/src/test/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMapTest.java
 
b/jena-geosparql/src/test/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMapTest.java
deleted file mode 100644
index b7129a1938..0000000000
--- 
a/jena-geosparql/src/test/java/org/apache/jena/ext/io/github/galbiston/expiring_map/ExpiringMapTest.java
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright 2018 the original author or authors.
- * See the notice.md file distributed with this work for additional
- * information regarding copyright ownership.
- *
- * Licensed 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 org.apache.jena.ext.io.github.galbiston.expiring_map;
-
-import org.junit.After;
-import org.junit.AfterClass;
-
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.MAP_CLEANER_INTERVAL;
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.MINIMUM_MAP_CLEANER_INTERVAL;
-import static 
org.apache.jena.ext.io.github.galbiston.expiring_map.MapDefaultValues.UNLIMITED_EXPIRY;
-import static org.junit.Assert.assertEquals;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- *
- *
- */
-public class ExpiringMapTest {
-
-    public ExpiringMapTest() {
-    }
-
-    @BeforeClass
-    public static void setUpClass() {
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-    }
-
-    @Before
-    public void setUp() {
-    }
-
-    @After
-    public void tearDown() {
-    }
-
-    /**
-     * Test of put method, of class ExpiringMap.
-     *
-     * @throws java.lang.InterruptedException
-     */
-    @Test
-    public void testExpiry() throws InterruptedException {
-        //System.out.println("expiry");
-
-        long expiryInterval = 2000l;
-        long cleanerInterval = 1000l;
-        long halfExpiryInterval = expiryInterval / 2;
-
-        ExpiringMap<String, String> instance = new ExpiringMap<>("Test", 5, 
expiryInterval, cleanerInterval);
-
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        instance.put("key3", "value3");
-        instance.put("key4", "value4");
-        instance.startExpiry();
-        Thread.sleep(halfExpiryInterval + 100);
-        instance.put("key5", "value5"); //Should be rejected.
-        instance.put("key6", "value6");
-        ////System.out.println("Size Before: " + instance.size());
-        Thread.sleep(halfExpiryInterval + cleanerInterval);
-        instance.stopExpiry();
-        ////System.out.println("Size After: " + instance.size());
-        int result = instance.size();
-        int expResult = 1;
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of put method, of class ExpiringMap.
-     *
-     * @throws java.lang.InterruptedException
-     */
-    @Test
-    public void testExpiry_none() throws InterruptedException {
-        //System.out.println("expiry_none");
-
-        ExpiringMap<String, String> instance = new ExpiringMap<>("Test");
-
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        instance.put("key3", "value3");
-        instance.put("key4", "value4");
-        instance.startExpiry();
-        Thread.sleep(1000);
-        instance.put("key5", "value5");
-        instance.put("key6", "value6");
-
-        ////System.out.println("Size Before: " + instance.size());
-        Thread.sleep(1000);
-        instance.stopExpiry();
-        ////System.out.println("Size After: " + instance.size());
-        int result = instance.size();
-        int expResult = 6;
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of put method, of class ExpiringMap.
-     *
-     * @throws java.lang.InterruptedException
-     */
-    @Test
-    public void testRefresh() throws InterruptedException {
-        //System.out.println("refresh");
-
-        long expiryInterval = 2000l;
-        long halfExpiryInterval = expiryInterval / 2;
-        long quarterExpiryInterval = expiryInterval / 3 * 4;
-
-        ExpiringMap<String, String> instance = new ExpiringMap<>("Test", 5, 
expiryInterval, halfExpiryInterval);
-
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        instance.put("key3", "value3");
-        instance.put("key4", "value4");
-        instance.startExpiry();
-        Thread.sleep(halfExpiryInterval + quarterExpiryInterval);
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        ////System.out.println("Size Before: " + instance.size());
-        Thread.sleep(halfExpiryInterval);
-        instance.stopExpiry();
-        ////System.out.println("Size After: " + instance.size());
-        int result = instance.size();
-        int expResult = 2;
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of put method, of class ExpiringMap.
-     *
-     * @throws java.lang.InterruptedException
-     */
-    @Test
-    public void testEmpty() throws InterruptedException {
-        //System.out.println("empty");
-
-        long expiryInterval = 2000l;
-        long cleanerInterval = 1000l;
-        long halfExpiryInterval = expiryInterval / 2;
-
-        ExpiringMap<String, String> instance = new ExpiringMap<>("Test", 5, 
expiryInterval, cleanerInterval);
-
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        instance.put("key3", "value3");
-        instance.put("key4", "value4");
-        instance.startExpiry();
-        Thread.sleep(halfExpiryInterval);
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        ////System.out.println("Size Before: " + instance.size());
-        Thread.sleep(expiryInterval + cleanerInterval);
-        instance.stopExpiry();
-        ////System.out.println("Size After: " + instance.size());
-        int result = instance.size();
-        int expResult = 0;
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of setCleanerInterval method, of class ExpiringMap.
-     */
-    @Test
-    public void testSetCleanerInterval() {
-        //System.out.println("setCleanerInterval");
-        long cleanerInterval = 2000L;
-        ExpiringMap<?,?> instance = new ExpiringMap<>("Test", 5);
-        instance.setCleanerInterval(cleanerInterval);
-        long expResult = cleanerInterval;
-        long result = instance.getCleanerInterval();
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of setCleanerInterval method, of class ExpiringMap.
-     */
-    @Test
-    public void testSetCleanerInterval_minimum() {
-        //System.out.println("setCleanerInterval_minimum");
-        long cleanerInterval = 0L;
-        ExpiringMap<?,?> instance = new ExpiringMap<>("Test", 5);
-        instance.setCleanerInterval(cleanerInterval);
-        long expResult = MINIMUM_MAP_CLEANER_INTERVAL;
-        long result = instance.getCleanerInterval();
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of setExpiryInterval method, of class ExpiringMap.
-     */
-    @Test
-    public void testSetExpiryInterval() {
-        //System.out.println("setExpiryInterval");
-        long expiryInterval = 2000L;
-        ExpiringMap<?,?> instance = new ExpiringMap<>("Test", 5);
-        instance.setExpiryInterval(expiryInterval);
-        long expResult = expiryInterval;
-        long result = instance.getExpiryInterval();
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of setExpiryInterval method, of class ExpiringMap.
-     */
-    @Test
-    public void testSetExpiryInterval_minimum() {
-        //System.out.println("setExpiryInterval_minimum");
-        long expiryInterval = 0L;
-        ExpiringMap<?,?> instance = new ExpiringMap<>("Test", 5);
-        instance.setExpiryInterval(expiryInterval);
-        long expResult = MAP_CLEANER_INTERVAL + 1;
-        long result = instance.getExpiryInterval();
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of isExpiring method, of class ExpiringMap.
-     */
-    @Test
-    public void testIsExpiring() {
-        //System.out.println("isExpiring");
-        long expiryInterval = 1000L;
-        ExpiringMap<?,?> instance = new ExpiringMap<>("Test", 5);
-        instance.setExpiryInterval(expiryInterval);
-        boolean expResult = true;
-        boolean result = instance.isExpiring();
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of isExpiring method, of class ExpiringMap.
-     */
-    @Test
-    public void testIsExpiring_false() {
-        //System.out.println("isExpiring_false");
-        long expiryInterval = UNLIMITED_EXPIRY;
-        ExpiringMap<?,?> instance = new ExpiringMap<>("Test", 5);
-        instance.setExpiryInterval(expiryInterval);
-        boolean expResult = false;
-        boolean result = instance.isExpiring();
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of put method, of class ExpiringMap.
-     *
-     * @throws java.lang.InterruptedException
-     */
-    @Test
-    public void testExpiry_change_max_size() throws InterruptedException {
-        //System.out.println("expiry_change_max_size");
-
-        long expiryInterval = 2000l;
-        long cleanerInterval = 1000l;
-        long halfExpiryInterval = expiryInterval / 2;
-
-        ExpiringMap<String, String> instance = new ExpiringMap<>("Test", 5, 
expiryInterval, cleanerInterval);
-
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        instance.put("key3", "value3");
-        instance.put("key4", "value4");
-        instance.startExpiry();
-        Thread.sleep(halfExpiryInterval + 100);
-        instance.setMaxSize(10);
-        instance.put("key5", "value5");
-        instance.put("key6", "value6");
-        ////System.out.println("Size Before: " + instance.size());
-        instance.stopExpiry();
-        ////System.out.println("Size After: " + instance.size());
-        int result = instance.size();
-        int expResult = 6;
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of put method, of class ExpiringMap.
-     *
-     * @throws java.lang.InterruptedException
-     */
-    @Test
-    public void testExpiry_change_max_size_reduced() throws 
InterruptedException {
-        //System.out.println("expiry_change_max_size_reduced");
-
-        long expiryInterval = 2000l;
-        long cleanerInterval = 1000l;
-        long halfExpiryInterval = expiryInterval / 2;
-
-        ExpiringMap<String, String> instance = new ExpiringMap<>("Test", 10, 
expiryInterval, cleanerInterval);
-
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        instance.put("key3", "value3");
-        instance.put("key4", "value4");
-        instance.startExpiry();
-        Thread.sleep(halfExpiryInterval + 100);
-
-        instance.put("key5", "value5");
-        instance.put("key6", "value6");
-        instance.setMaxSize(5);
-        instance.put("key7", "value7"); //Should be rejected.
-        ////System.out.println("Size Before: " + instance.size());
-        instance.stopExpiry();
-        ////System.out.println("Size After: " + instance.size());
-        int result = instance.size();
-        int expResult = 6;  //Over max size but don't remove until expired.
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of put method, of class ExpiringMap.
-     *
-     * @throws java.lang.InterruptedException
-     */
-    @Test
-    public void testExpiry_change_expiry_interval() throws 
InterruptedException {
-        //System.out.println("expiry_change_expiry_interval");
-
-        long expiryInterval = 2000l;
-        long cleanerInterval = 1000l;
-        long halfExpiryInterval = expiryInterval / 2;
-
-        ExpiringMap<String, String> instance = new ExpiringMap<>("Test", 10, 
expiryInterval, cleanerInterval);
-
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        instance.put("key3", "value3");
-        instance.put("key4", "value4");
-        instance.startExpiry();
-        Thread.sleep(halfExpiryInterval + 100);
-        instance.put("key5", "value5");
-        instance.put("key6", "value6");
-        instance.setExpiryInterval(4000l);
-        ////System.out.println("Size Before: " + instance.size());
-        Thread.sleep(halfExpiryInterval + cleanerInterval); //No cleaning 
should have taken place.
-        instance.stopExpiry();
-        ////System.out.println("Size After: " + instance.size());
-        int result = instance.size();
-        int expResult = 6;
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of put method, of class ExpiringMap.
-     *
-     * @throws java.lang.InterruptedException
-     */
-    @Test
-    public void testExpiry_change_expiry_interval_reduced() throws 
InterruptedException {
-        //System.out.println("expiry_change_expiry_interval_reduced");
-
-        long expiryInterval = 4000l;
-        long cleanerInterval = 1000l;
-        long halfExpiryInterval = expiryInterval / 2;
-
-        ExpiringMap<String, String> instance = new ExpiringMap<>("Test", 10, 
expiryInterval, cleanerInterval);
-
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        instance.put("key3", "value3");
-        instance.put("key4", "value4");
-        instance.startExpiry();
-        Thread.sleep(halfExpiryInterval + 100);
-        instance.put("key5", "value5");
-        instance.put("key6", "value6");
-        instance.setExpiryInterval(2000l);
-        ////System.out.println("Size Before: " + instance.size());
-        Thread.sleep(halfExpiryInterval + cleanerInterval); //All should have 
been removed.
-        instance.stopExpiry();
-        ////System.out.println("Size After: " + instance.size());
-        int result = instance.size();
-        int expResult = 0;
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of put method, of class ExpiringMap.
-     *
-     * @throws java.lang.InterruptedException
-     */
-    @Test
-    public void testExpiry_set_cleaner() throws InterruptedException {
-        //System.out.println("expiry_set_cleaner");
-
-        long expiryInterval = 2000l;
-        long cleanerInterval = 1000l;
-        long halfExpiryInterval = expiryInterval / 2;
-
-        ExpiringMap<String, String> instance = new ExpiringMap<>("Test", 5, 
expiryInterval, cleanerInterval);
-
-        instance.put("key1", "value1");
-        instance.put("key2", "value2");
-        instance.put("key3", "value3");
-        instance.put("key4", "value4");
-        instance.startExpiry();
-        Thread.sleep(halfExpiryInterval + 100);
-        instance.setCleanerInterval(500l); //No obvious effect should occur.
-        instance.put("key5", "value5"); //Should be rejected.
-        instance.put("key6", "value6");
-        ////System.out.println("Size Before: " + instance.size());
-        Thread.sleep(halfExpiryInterval + cleanerInterval);
-        instance.stopExpiry();
-        ////System.out.println("Size After: " + instance.size());
-        int result = instance.size();
-        int expResult = 1;
-
-        ////System.out.println("Exp: " + expResult);
-        ////System.out.println("Res: " + result);
-        assertEquals(expResult, result);
-    }
-
-}
diff --git 
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/index/CacheConfigurationTest.java
 
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/index/CacheConfigurationTest.java
new file mode 100644
index 0000000000..b0d5c67554
--- /dev/null
+++ 
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/index/CacheConfigurationTest.java
@@ -0,0 +1,79 @@
+package org.apache.jena.geosparql.implementation.index;
+
+import org.apache.jena.atlas.lib.Cache;
+import org.apache.jena.atlas.lib.cache.CacheCaffeine;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CacheConfigurationTest {
+
+    @Test
+    public void cache_creation_null() {
+        Cache<String, String> cache = 
CacheConfiguration.create(CacheConfiguration.NO_MAP, 0L);
+        cache.put("test", "test");
+        Assert.assertFalse(cache.containsKey("test"));
+    }
+
+    @Test
+    public void cache_creation_simple_01() {
+        Cache<Integer, String> cache = CacheConfiguration.create(100, 0L);
+
+        for (int i = 0; i < 1_000; i++) {
+            cache.put(i, Integer.toString(i));
+        }
+
+        // Should be fewer items than we added since we exceeded the max size
+        forceCleanUp(cache);
+        Assert.assertNotEquals(1_000, cache.size());
+    }
+
+    @Test
+    public void cache_creation_simple_02() {
+        Cache<Integer, String> cache = CacheConfiguration.create(100_000, 0L);
+
+        for (int i = 0; i < 1_000; i++) {
+            cache.put(i, Integer.toString(i));
+        }
+
+        // Should be exactly as many items as we added as we aren't remotely 
near the max size
+        forceCleanUp(cache);
+        Assert.assertEquals(1_000, cache.size());
+    }
+
+    @Test
+    public void cache_creation_unlimited() {
+        Cache<Integer, String> cache = 
CacheConfiguration.create(CacheConfiguration.UNLIMITED_MAP, 0L);
+
+        for (int i = 0; i < 1_000; i++) {
+            cache.put(i, Integer.toString(i));
+        }
+
+        // Should be exactly as many items as we added as we aren't remotely 
near the max size
+        forceCleanUp(cache);
+        Assert.assertEquals(1_000, cache.size());
+    }
+
+    @Test
+    public void cache_creation_expiring() throws InterruptedException {
+        Cache<Integer, String> cache = CacheConfiguration.create(100, 100);
+
+        for (int i = 0; i < 1_000; i++) {
+            cache.put(i, Integer.toString(i));
+        }
+
+        // Should be fewer items than we added since we exceeded the max size
+        forceCleanUp(cache);
+        Assert.assertNotEquals(1_000L, cache.size());
+
+        // Wait for everything to expire and check now empty
+        Thread.sleep(250L);
+        forceCleanUp(cache);
+        Assert.assertEquals(0L, cache.size());
+    }
+
+    private static <K, V> void forceCleanUp(Cache<K, V> cache) {
+        if (cache instanceof CacheCaffeine<K, V> caffeine) {
+            caffeine.cleanUp();
+        }
+    }
+}

Reply via email to