package org.gcube.application.geoportal.service.engine.providers; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.Synchronized; import lombok.extern.slf4j.Slf4j; import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException; import org.gcube.application.geoportal.service.utils.ContextUtils; import java.time.LocalDateTime; import java.time.temporal.TemporalAmount; import java.util.concurrent.ConcurrentHashMap; @Slf4j @RequiredArgsConstructor public abstract class AbstractScopedMap implements Engine{ // scope-> object private ConcurrentHashMap> scopeMap=new ConcurrentHashMap>(); @Setter private TemporalAmount TTL=null; @NonNull private String name; @Synchronized public T getObject() throws ConfigurationException { String currentScope=ContextUtils.getCurrentScope(); log.debug(name+" : obtaining object for context "+currentScope); TTLObject found=scopeMap.get(currentScope); if(found== null){ log.debug(name+" : init object for context "+currentScope); TTLObject toPut=new TTLObject(LocalDateTime.now(),retrieveObject()); scopeMap.put(currentScope, toPut); return toPut.getTheObject(); } if(TTL!=null) { if(found.getCreationTime().plus(TTL).isBefore(LocalDateTime.now())) { log.debug(name+" : elapsed TTL, disposing.."); dispose(found.getTheObject()); TTLObject newer=new TTLObject(LocalDateTime.now(),retrieveObject()); scopeMap.put(currentScope, newer); found=scopeMap.get(currentScope); } }else {log.debug(name+" : TTL is null, never disposing..");} log.debug("Returning {} ",found); return found.getTheObject(); } @Override public void shutdown() { log.warn(name + ": shutting down"); scopeMap.forEach((String s,TTLObject o)->{ try{if(o!=null&&o.getTheObject()!=null) dispose(o.getTheObject()); }catch(Throwable t) { log.warn(name +": unable to dispose ",t); } }); } protected abstract T retrieveObject() throws ConfigurationException; protected abstract void dispose(T toDispose); }