package net.curisit.securis.utils; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Singleton; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * Cache implementation with TTL (time To Live) The objects are removed from * cache when TTL is reached. * * @author roberto */ @Singleton public class CacheTTL { private static final Logger LOG = LogManager.getLogger(CacheTTL.class); /** * Period before token expires, set in seconds. */ private static int DEFAULT_CACHE_DURATION = 24 * 60 * 60; private Map data = new HashMap<>(); private Thread cleaningThread = null; @Inject public CacheTTL() { cleaningThread = new Thread(new Runnable() { @Override public void run() { while (CacheTTL.this.data != null) { try { // We check for expired object every 60 seconds Thread.sleep(60 * 1000); } catch (InterruptedException e) { LOG.error("Exiting from Cache Thread"); data.clear(); return; } Date now = new Date(); List keysToRemove = new ArrayList<>(); for (String key : CacheTTL.this.data.keySet()) { CachedObject co = CacheTTL.this.data.get(key); if (now.after(co.getExpireAt())) { keysToRemove.add(key); } } for (String key : keysToRemove) { // If we try to remove directly in the previous loop an // exception is thrown // java.util.ConcurrentModificationException CacheTTL.this.data.remove(key); } } } }); cleaningThread.start(); } /** * * @param key * @param obj * @param ttl * Time To Live in seconds */ public void set(String key, Object obj, int ttl) { Date expirationDate = new Date(new Date().getTime() + ttl * 1000); data.put(key, new CachedObject(expirationDate, obj)); } public void set(String key, Object obj) { set(key, obj, DEFAULT_CACHE_DURATION); } public Object get(String key) { CachedObject co = data.get(key); return co == null ? null : co.getObject(); } public T get(String key, Class type) { CachedObject co = data.get(key); return co == null ? null : co.getObject(type); } public T remove(String key, Class type) { CachedObject co = data.remove(key); return co == null ? null : co.getObject(type); } public Object remove(String key) { CachedObject co = data.remove(key); return co == null ? null : co.getObject(); } public void clear() { data.clear(); } private class CachedObject { Date expireAt; Object object; public CachedObject(Date date, Object obj) { expireAt = date; object = obj; } public Date getExpireAt() { return expireAt; } public Object getObject() { return object; } @SuppressWarnings("unchecked") public T getObject(Class type) { return (T) object; } } }