ConfigManager.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.core.mvc.properties.utils;

  21. import java.io.ByteArrayInputStream;
  22. import java.io.File;
  23. import java.util.ArrayList;
  24. import java.util.Arrays;
  25. import java.util.Collections;
  26. import java.util.HashMap;
  27. import java.util.Iterator;
  28. import java.util.List;
  29. import java.util.Map;

  30. import org.openspcoop2.core.commons.CoreException;
  31. import org.openspcoop2.core.mvc.properties.Compatibility;
  32. import org.openspcoop2.core.mvc.properties.Config;
  33. import org.openspcoop2.core.mvc.properties.Tags;
  34. import org.openspcoop2.core.mvc.properties.utils.serializer.JaxbDeserializer;
  35. import org.openspcoop2.generic_project.exception.DeserializerException;
  36. import org.openspcoop2.utils.xml.AbstractValidatoreXSD;
  37. import org.slf4j.Logger;

  38. /**    
  39.  * Manager delle configurazioni disponibili.
  40.  *
  41.  * @author Pintori Giuliano (pintori@link.it)
  42.  * @author $Author$
  43.  * @version $Rev$, $Date$
  44.  */
  45. public class ConfigManager {

  46.     private static ConfigManager instance = null;
  47.     private Logger log = null;
  48.     private Map<String, Map<String,Config>> mapConfigBuildIn = null;
  49.     private Map<String, Map<String,Config>> mapConfigFileSystem = null;
  50.     private Map<String, Map<String,Config>> mapConfig = null;
  51.     private AbstractValidatoreXSD validator = null;
  52.    
  53.     public static ConfigManager getinstance(Logger log) throws CoreException {
  54.         if(instance == null) {
  55.             // spotbugs warning 'SING_SINGLETON_GETTER_NOT_SYNCHRONIZED'
  56.             synchronized (ConfigManager.class) {
  57.                 init(log);
  58.             }
  59.         }
  60.         return instance;
  61.     }
  62.    
  63.     private static synchronized void init(Logger log) throws CoreException{
  64.         instance = new ConfigManager(log);
  65.     }
  66.    
  67.    
  68.     private ConfigManager(Logger log) throws CoreException  {
  69.         this.log = log;
  70.         this.mapConfigBuildIn = new HashMap<>();
  71.         this.mapConfigFileSystem = new HashMap<>();
  72.         this.mapConfig = new HashMap<>();
  73.        
  74.         try {
  75.             this.validator = XSDValidator.getXSDValidator(log);
  76.         }catch(Exception e) {
  77.             doError("Errore durante la init del ManagerConfigurazioni",e);
  78.         }
  79.     }
  80.     private void doError(String msg,Exception e) throws CoreException {
  81.         String msgError = msg +": "+ e.getMessage();
  82.         this.log.error(msgError,e);
  83.         throw new CoreException(e.getMessage(),e);
  84.     }
  85.    
  86.    
  87.     public void leggiConfigurazioni(PropertiesSourceConfiguration propertiesSourceConfiguration, boolean validazioneXSD) throws CoreException, DeserializerException{
  88.         // Configurazioni builtIn
  89.         if(!this.mapConfigBuildIn.containsKey(propertiesSourceConfiguration.getId()) || propertiesSourceConfiguration.isUpdateBuiltIn()) {
  90.             if(this.mapConfigBuildIn.containsKey(propertiesSourceConfiguration.getId())) {
  91.                 this.mapConfigBuildIn.remove(propertiesSourceConfiguration.getId());
  92.             }
  93.            
  94.             Map<String,Config> mapConfigFromDir = null;
  95.            
  96.             List<byte[]> builtIn = propertiesSourceConfiguration.getBuiltIn();
  97.            
  98.             if(builtIn != null && !builtIn.isEmpty()) {
  99.                 mapConfigFromDir = new HashMap<>();
  100.                 JaxbDeserializer xmlReader = new JaxbDeserializer();
  101.                 for (int i = 0 ; i < builtIn.size(); i++ ) {
  102.                     byte[] f = builtIn.get(i);
  103.                     // validazione XSD se prevista
  104.                     if(validazioneXSD) {
  105.                         try {
  106.                             this.validator.valida(new ByteArrayInputStream(f));
  107.                         }catch(Exception e) {
  108.                             doError("La configurazione builtIn numero ["+(i+1)+"] non e' valida",e);
  109.                         }
  110.                     }
  111.                    
  112.                     Config configDaFile = xmlReader.readConfig(f);
  113.                     String id = configDaFile.getId();
  114.                     if(mapConfigFromDir.containsKey(id))
  115.                         throw new CoreException("La configurazione builtIn con id '"+id+"' risulta duplicata all'interno di quelle precaricate nel sistema.");
  116.                        
  117.                     mapConfigFromDir.put(id,configDaFile);
  118.                 }
  119.                 this.mapConfigBuildIn.put(propertiesSourceConfiguration.getId(), mapConfigFromDir);
  120.             }
  121.         }
  122.        
  123.         // configurazioni da file system
  124.         if(propertiesSourceConfiguration.getDirectory() != null && (!this.mapConfigFileSystem.containsKey(propertiesSourceConfiguration.getId()) || propertiesSourceConfiguration.isUpdate())) {
  125.             if(this.mapConfigFileSystem.containsKey(propertiesSourceConfiguration.getId())) {
  126.                 this.mapConfigFileSystem.remove(propertiesSourceConfiguration.getId());
  127.             }
  128.            
  129.             Map<String,Config> mapConfigFromDir = null;
  130.            
  131.             File dir = new File(propertiesSourceConfiguration.getDirectory());
  132.            
  133.             if(!dir.exists())
  134.                 throw new CoreException("Il path indicato ["+propertiesSourceConfiguration.getDirectory()+"] non esiste, impossibile leggere le configurazioni");
  135.            
  136.             if(!dir.isDirectory())
  137.                 throw new CoreException("Il path indicato ["+propertiesSourceConfiguration.getDirectory()+"] non e' una directory");
  138.            
  139.             String[] fileList = dir.list();
  140.            
  141.             if(fileList != null && fileList.length > 0) {
  142.                 mapConfigFromDir = new HashMap<>();
  143.                 JaxbDeserializer xmlReader = new JaxbDeserializer();
  144.                 for (String f : fileList) {
  145.                     File fileConfig = new File(dir.getPath() + File.separator + f);
  146.                     if(!fileConfig.isDirectory()) {
  147.                         // validazione XSD se prevista
  148.                         if(validazioneXSD) {
  149.                             try {
  150.                                 this.validator.valida(fileConfig);
  151.                             }catch(Exception e) {
  152.                                 doError("La configurazione ["+fileConfig.getName()+"] non e' valida",e);
  153.                             }
  154.                         }
  155.                        
  156.                         Config configDaFile = xmlReader.readConfig(fileConfig);
  157.                         String id = configDaFile.getId();
  158.                         if(mapConfigFromDir.containsKey(id))
  159.                             throw new CoreException("La configurazione con id '"+id+"' risulta duplicata all'interno del path indicato ["+propertiesSourceConfiguration.getDirectory()+"].");
  160.                            
  161.                         mapConfigFromDir.put(id,configDaFile);
  162.                     }
  163.                 }
  164.                 this.mapConfigFileSystem.put(propertiesSourceConfiguration.getId(), mapConfigFromDir);
  165.             }
  166.         }
  167.        
  168.         // merge configurazioni
  169.         if(!this.mapConfig.containsKey(propertiesSourceConfiguration.getId()) || propertiesSourceConfiguration.isUpdateBuiltIn() || propertiesSourceConfiguration.isUpdate()) {
  170.             if(this.mapConfig.containsKey(propertiesSourceConfiguration.getId())) {
  171.                 this.mapConfig.remove(propertiesSourceConfiguration.getId());
  172.             }
  173.            
  174.             Map<String, Config> mapBuiltIn = this.mapConfigBuildIn.get(propertiesSourceConfiguration.getId());
  175.             Map<String, Config> mapFileSystem = this.mapConfigFileSystem.get(propertiesSourceConfiguration.getId());
  176.            
  177.             if(mapBuiltIn != null && mapBuiltIn.size() > 0 && mapFileSystem != null && mapFileSystem.size() > 0 ) {
  178.                 // controllo duplicati
  179.                 for (String keyBuiltIn : mapBuiltIn.keySet()) {
  180.                     if(mapFileSystem.keySet().contains(keyBuiltIn))
  181.                         throw new CoreException("La configurazione con id '"+keyBuiltIn+"' risulta duplicata, e' presente sia come configurazione builtIn che come configurazione esterna, eliminare una delle due.");
  182.                 }
  183.             }
  184.            
  185.             Map<String, Config> map = new HashMap<>();
  186.             if(mapBuiltIn != null && mapBuiltIn.size() > 0)
  187.                 map.putAll(mapBuiltIn);
  188.             if(mapFileSystem != null && mapFileSystem.size() > 0)
  189.                 map.putAll(mapFileSystem);
  190.            
  191.             this.mapConfig.put(propertiesSourceConfiguration.getId(), map);
  192.         }
  193.     }
  194.    
  195.     public List<String> getNomiConfigurazioni(PropertiesSourceConfiguration propertiesSourceConfiguration, String ... tags) {
  196.         List<String> mapSortedKeys = new ArrayList<>();
  197.         Map<String, List<String>> mapSorted = new HashMap<>();
  198.                
  199.         Map<String, Config> map = this.mapConfig.get(propertiesSourceConfiguration.getId());

  200.         Iterator<String> iterator = map.keySet().iterator();
  201.         while (iterator.hasNext()) {
  202.             String id = iterator.next();
  203.            
  204.             Config config = map.get(id);
  205.             if(tags!=null && tags.length>0) {
  206.                 Compatibility compatibility = config.getCompatibility();
  207.                 // se non e' compatibile con i tag richiesti non lo aggiungo alla lista
  208.                 if(!checkCompatibility(compatibility, Arrays.asList(tags)))
  209.                     continue;
  210.             }
  211.            
  212.             String labelId = config.getLabel();
  213.             if(config.getSortLabel()!=null) {
  214.                 labelId = config.getSortLabel();
  215.             }
  216.            
  217.             List<String> l = null;
  218.             if(mapSorted.containsKey(labelId)) {
  219.                 l = mapSorted.get(labelId);
  220.             }
  221.             else {
  222.                 l = new ArrayList<>();
  223.                 mapSorted.put(labelId, l);
  224.                 mapSortedKeys.add(labelId);
  225.             }
  226.             l.add(id);
  227.            
  228.         }
  229.        
  230.         Collections.sort(mapSortedKeys);
  231.         List<String> list = new ArrayList<>();
  232.         for (String labelId : mapSortedKeys) {
  233.             List<String> l = mapSorted.get(labelId);
  234.             list.addAll(l);
  235.         }
  236.         return list; // lista contenente gli id
  237.     }
  238.    
  239.     public List<String> convertToLabel(PropertiesSourceConfiguration propertiesSourceConfiguration, List<String> idList){
  240.    
  241.         Map<String, Config> map = this.mapConfig.get(propertiesSourceConfiguration.getId());
  242.         List<String> listLabels = new ArrayList<>();
  243.         for (String id : idList) {
  244.             Config config = map.get(id);
  245.             String labelId = config.getLabel();
  246.             /**if(config.getSortLabel()!=null) {
  247.                 labelId = config.getSortLabel();
  248.             }*/
  249.             listLabels.add(labelId);
  250.         }
  251.         return listLabels;
  252.     }
  253.    
  254.     public Config getConfigurazione(PropertiesSourceConfiguration propertiesSourceConfiguration, String name){
  255.         return this.mapConfig.get(propertiesSourceConfiguration.getId()).get(name);
  256.     }
  257.    
  258.     public boolean checkCompatibility(Compatibility compatibility, List<String> tags) {
  259.         if(compatibility == null)
  260.             return true;
  261.        
  262.         boolean isAnd = compatibility.getAnd();
  263.         boolean isNot = compatibility.getNot();
  264.        
  265.         // Valore di partenza dell'esito totale e'
  266.         // TRUE se devo controllare l'and dei tag
  267.         // FALSE se devo controllare l'or dei tag
  268.         boolean esito = isAnd;

  269.         for (Tags tag : compatibility.getTagsList()) {
  270.             boolean resCondition = checkTags(tag,tags);

  271.             // aggiorno l'esito in base all'operazione da aggregare AND o OR
  272.             esito = isAnd ? (esito && resCondition) : (esito || resCondition);
  273.         }

  274.         // eventuale NOT della condizione
  275.         return isNot ? !esito : esito;
  276.     }

  277.     private boolean checkTags(Tags tag, List<String> tags) {
  278.         boolean isAnd = tag.getAnd();
  279.         boolean isNot = tag.getNot();
  280.        
  281.         // Valore di partenza dell'esito totale e'
  282.         // TRUE se devo controllare l'and dei tag
  283.         // FALSE se devo controllare l'or dei tag
  284.         boolean esito = isAnd;
  285.        
  286.         for (String stringTag : tag.getTagList()) {
  287.             boolean resCondition = tags.contains(stringTag);
  288.             // aggiorno l'esito in base all'operazione da aggregare AND o OR
  289.             esito = isAnd ? (esito && resCondition) : (esito || resCondition);
  290.         }
  291.        
  292.         // eventuale NOT della condizione
  293.         return isNot ? !esito : esito;
  294.     }
  295.    
  296. }