AbstractKeystoreCache.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.security.keystore.cache;

  21. import java.io.Serializable;
  22. import java.util.ArrayList;
  23. import java.util.Arrays;
  24. import java.util.Date;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.concurrent.ConcurrentHashMap;

  28. import org.apache.commons.codec.digest.DigestUtils;
  29. import org.openspcoop2.security.SecurityException;
  30. import org.openspcoop2.utils.SemaphoreLock;
  31. import org.openspcoop2.utils.cache.Cache;
  32. import org.openspcoop2.utils.date.DateManager;
  33. import org.openspcoop2.utils.date.DateUtils;

  34. /**
  35.  * AbstractKeystoreCache
  36.  *
  37.  * @author Andrea Poli (apoli@link.it)
  38.  * @author $Author$
  39.  * @version $Rev$, $Date$
  40.  */
  41. public abstract class AbstractKeystoreCache<T extends Serializable> {

  42.     private int cacheLifeSecond = -1;
  43.     private int cacheSize = -1;
  44.    
  45.     private Map<String, KeystoreCacheEntry<T>> cacheMap = new ConcurrentHashMap<>();
  46.     private Cache cacheJCS = null;
  47.     private final org.openspcoop2.utils.Semaphore lockCache = new org.openspcoop2.utils.Semaphore(this.getClass().getSimpleName());

  48.     public void setKeystoreCacheParameters(int cacheLifeSecond,int cacheSize){
  49.         this.cacheLifeSecond = cacheLifeSecond;
  50.         this.cacheSize = cacheSize;
  51.     }
  52.     public void setCacheJCS(int cacheLifeSecond,Cache cacheJCS) {
  53.         this.cacheLifeSecond = cacheLifeSecond;
  54.         this.cacheJCS = cacheJCS;
  55.     }
  56.     public void updateCacheLifeSecond(int cacheLifeSecond) {
  57.         this.cacheLifeSecond = cacheLifeSecond;
  58.     }
  59.    
  60.    
  61.    
  62.     public T getKeystore(String keyParam) throws SecurityException{
  63.         KeystoreCacheEntry<T> o = this.getObjectFromCache(keyParam);
  64.         if(o==null){
  65.             throw new SecurityException("Keystore with key ["+keyParam+"] not found");
  66.         }
  67.         else {
  68.             return estraiKeystore(o);
  69.         }
  70.     }
  71.     public T getKeystoreAndCreateIfNotExists(String keyParam,Object ... params) throws SecurityException{
  72.         KeystoreCacheEntry<T> o = this.getObjectFromCache(keyParam);
  73.         if(o==null){
  74.             /**System.out.println("NON trovato ["+key+"], creo...");*/
  75.             return initKeystore(keyParam, params);
  76.         }
  77.         else {
  78.             /**System.out.println("GIA PRESENTE ["+key+"] ESTRAGGO");*/
  79.             return estraiKeystore(o);
  80.         }
  81.     }
  82.    
  83.     public T getKeystore(byte[] keystore) throws SecurityException{
  84.         String keyParam = buildKeyCacheFromBytes(keystore);
  85.         return getKeystore(keyParam);
  86.     }
  87.     public T getKeystoreAndCreateIfNotExists(byte[] keystore,Object ... params) throws SecurityException{
  88.         String keyParam = buildKeyCacheFromBytes(keystore);
  89.         List<Object> lArgs = new ArrayList<>();
  90.         lArgs.add(keystore);
  91.         if(params!=null && params.length>0) {
  92.             lArgs.addAll(Arrays.asList(params));
  93.         }
  94.         return getKeystoreAndCreateIfNotExists(keyParam, lArgs.toArray());
  95.     }
  96.    
  97.     public abstract T createKeystore(String key,Object ... params) throws SecurityException;
  98.     public abstract String getPrefixKey();
  99.    
  100.    
  101.     /* UTILITY */
  102.    
  103.     public static String buildKeyCacheFromBytes(byte[] keystore) throws SecurityException {
  104.         if(keystore==null) {
  105.             throw new SecurityException("Keystore undefined");
  106.         }
  107.         return DigestUtils.sha256Hex(keystore);
  108.     }
  109.    
  110.     @SuppressWarnings("unchecked")
  111.     private KeystoreCacheEntry<T> getObjectFromCache(String keyParam) {
  112.         String keyCache = this.getPrefixKey() + keyParam;
  113.         KeystoreCacheEntry<T> o = null;
  114.         if(this.cacheJCS!=null) {
  115.             Object object = this.cacheJCS.get(keyCache);
  116.             if(object!=null) {
  117.                 o = (KeystoreCacheEntry<T>) object;
  118.             }
  119.         }
  120.         else {
  121.             o = this.cacheMap.get(keyCache);
  122.         }
  123.         return o;
  124.     }
  125.        
  126.     private T initKeystore(String keyParam,Object ... params) throws SecurityException{
  127.        
  128.         SemaphoreLock lock = this.lockCache.acquireThrowRuntime("initKeystore");
  129.         try {
  130.             String keyCache = this.getPrefixKey() + keyParam;
  131.             KeystoreCacheEntry<T> o = this.getObjectFromCache(keyCache);
  132.             if(o==null) {
  133.                 T keystore = createKeystore(keyParam, params);
  134.                 KeystoreCacheEntry<T> cacheEntry = new KeystoreCacheEntry<>();
  135.                 cacheEntry.setKey(keyCache);
  136.                 cacheEntry.setKeystore(keystore);
  137.                 cacheEntry.setDate(DateManager.getDate());
  138.                 if(this.cacheJCS!=null) {
  139.                     try {
  140.                         this.cacheJCS.put(keyCache, cacheEntry);
  141.                     }catch(Exception e) {
  142.                         throw new SecurityException(e.getMessage(),e);
  143.                     }
  144.                 }
  145.                 else {
  146.                     this.cacheMap.put(keyCache, cacheEntry);
  147.                 }
  148.                 /**System.out.println("CREATO ["+key+"] !!!! DATA["+cacheEntry.getDate()+"]"); */
  149.                 return keystore;
  150.             }
  151.             else {
  152.                 return estraiKeystore(o);
  153.             }
  154.         }finally {
  155.             this.lockCache.release(lock, "initKeystore");
  156.         }
  157.        
  158.     }
  159.    
  160.     private void removeKeystore(String key) throws SecurityException{
  161.        
  162.         SemaphoreLock lock = this.lockCache.acquireThrowRuntime("removeKeystore");
  163.         try {
  164.             if(this.cacheJCS!=null) {
  165.                 try {
  166.                     this.cacheJCS.remove(key);
  167.                 }catch(Exception e) {
  168.                     throw new SecurityException(e.getMessage(),e);
  169.                 }
  170.             }
  171.             else {
  172.                 this.cacheMap.remove(key);
  173.             }
  174.         }finally {
  175.             this.lockCache.release(lock, "removeKeystore");
  176.         }
  177.        
  178.     }
  179.     public void removeObjectFromCache(String keyParam) throws SecurityException {
  180.         String keyCache = this.getPrefixKey() + keyParam;
  181.         removeKeystore(keyCache);
  182.     }
  183.    
  184.     public List<String> keys() throws SecurityException{
  185.         List<String> keys = new ArrayList<>();
  186.         SemaphoreLock lock = this.lockCache.acquireThrowRuntime("keys");
  187.         try {
  188.             if(this.cacheJCS!=null) {
  189.                 try {
  190.                     List<String> l = this.cacheJCS.keys();
  191.                     if(l!=null && !l.isEmpty()) {
  192.                         keys.addAll(l);
  193.                     }
  194.                 }catch(Exception e) {
  195.                     throw new SecurityException(e.getMessage(),e);
  196.                 }
  197.             }
  198.             else {
  199.                 if(!this.cacheMap.isEmpty()) {
  200.                     keys.addAll(this.cacheMap.keySet());
  201.                 }
  202.             }
  203.         }finally {
  204.             this.lockCache.release(lock, "keys");
  205.         }
  206.         return keys;
  207.     }
  208.    
  209.     private T estraiKeystore(KeystoreCacheEntry<T> entry) throws SecurityException{
  210.        
  211.         T keystore = entry.getKeystore();
  212.         if(this.cacheLifeSecond>-1){
  213.             long scadenza = entry.getDate().getTime()+this.cacheLifeSecond*1000;
  214.             long now = DateManager.getTimeMillis();
  215.             if(scadenza<now){
  216.                 /**System.out.println("SCADUTO PER DATA ["+entry.getKey()+"] ["+scadenza+"] ["+now+"]");*/
  217.                 removeKeystore(entry.getKey());
  218.             }
  219.         }
  220.         if(this.cacheJCS==null &&
  221.             this.cacheSize>-1 &&
  222.             this.cacheMap.size()>this.cacheSize){
  223.             /**System.out.println("ECCEDUTA DIMENSIONE ["+entry.getKey()+"]");*/
  224.             clearCacheMap();
  225.         }
  226.         return keystore;
  227.     }
  228.     private void clearCacheMap(){
  229.         SemaphoreLock lock = this.lockCache.acquireThrowRuntime("clearCacheMap");
  230.         try {
  231.             this.cacheMap.clear();
  232.         }finally {
  233.             this.lockCache.release(lock, "clearCacheMap");
  234.         }
  235.     }
  236.    
  237.    
  238.    
  239.    
  240. }
  241. class KeystoreCacheEntry<T extends Serializable> implements Serializable {
  242.    
  243.     /**
  244.      *
  245.      */
  246.     private static final long serialVersionUID = 1L;
  247.    
  248.     @Override
  249.     public String toString() {
  250.         StringBuilder bf = new StringBuilder();
  251.         bf.append("Data ").append(DateUtils.getSimpleDateFormatMs().format(this.date)).append("\n");
  252.         bf.append(this.keystore.toString());
  253.         return bf.toString();
  254.     }
  255.    
  256.     private String key;
  257.     private T keystore;
  258.     private Date date;
  259.    
  260.     public T getKeystore() {
  261.         return this.keystore;
  262.     }
  263.     public void setKeystore(T keystore) {
  264.         this.keystore = keystore;
  265.     }
  266.     public Date getDate() {
  267.         return this.date;
  268.     }
  269.     public void setDate(Date date) {
  270.         this.date = date;
  271.     }
  272.     public String getKey() {
  273.         return this.key;
  274.     }
  275.     public void setKey(String key) {
  276.         this.key = key;
  277.     }
  278.    
  279. }