DiagnosticProperties.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.utils.logger;

  21. import java.util.Arrays;
  22. import java.util.Enumeration;
  23. import java.util.HashMap;
  24. import java.util.Map;
  25. import java.util.Properties;

  26. import org.openspcoop2.utils.Utilities;
  27. import org.openspcoop2.utils.UtilsException;
  28. import org.openspcoop2.utils.logger.constants.LowSeverity;
  29. import org.openspcoop2.utils.logger.constants.Severity;

  30. /**
  31.  * DiagnosticManager
  32.  *
  33.  * @author Poli Andrea (apoli@link.it)
  34.  * @author $Author$
  35.  * @version $Rev$, $Date$
  36.  */
  37. public class DiagnosticProperties implements Cloneable{

  38.     private static DiagnosticProperties staticInstance;
  39.     private static synchronized void initialize(Properties diagnosticProperties, boolean throwExceptionPlaceholderFailedResolution) throws UtilsException{
  40.         if(staticInstance==null){
  41.             staticInstance = new DiagnosticProperties(diagnosticProperties, throwExceptionPlaceholderFailedResolution);
  42.         }
  43.     }
  44.     protected static DiagnosticProperties getInstance(Properties diagnosticProperties, boolean throwExceptionPlaceholderFailedResolution) throws UtilsException{
  45.         if(staticInstance==null){
  46.             initialize(diagnosticProperties, throwExceptionPlaceholderFailedResolution);
  47.         }
  48.         return staticInstance;
  49.     }
  50.    
  51.     public static final String EMPTY = "empty";
  52.    
  53.     private static final String PREFIX_FUNCTION = "function.";
  54.     private static final String PREFIX_DIAGNOSTIC = "diagnostic.";
  55.     private static final String SUFFIX_DIAGNOSTIC_CODE = ".code";
  56.     private static final String SUFFIX_DIAGNOSTIC_MESSAGE = ".message";
  57.     private static final String SUFFIX_DIAGNOSTIC_SEVERITY = ".severity";
  58.    
  59.     private static final String DEFAULT_FUNCTION = "default.function";
  60.    
  61.     private static final String DEFAULT_SEVERITY_CODE_PREFIX = "default.severity.";
  62.    
  63.     private Properties diagnosticProperties;
  64.    
  65.     private Map<String, String> mappingFunctionToCode = new HashMap<>();
  66.     private Map<String, String> mappingFullCodeToFullString = new HashMap<>();
  67.     private Map<String, DiagnosticInfo> mappingStringCodeToDiagnostic = new HashMap<String, DiagnosticInfo>();
  68.    
  69.     private String defaultFunction;
  70.     private Map<LowSeverity, String> mappingSeverityToCode = new HashMap<LowSeverity, String>();
  71.    
  72.     private boolean throwExceptionPlaceholderFailedResolution;
  73.    
  74.    
  75.     private DiagnosticProperties(Properties diagnosticProperties, boolean throwExceptionPlaceholderFailedResolution) throws UtilsException{
  76.         this.diagnosticProperties = diagnosticProperties;
  77.        
  78.         this.throwExceptionPlaceholderFailedResolution = throwExceptionPlaceholderFailedResolution;
  79.                
  80.         this.init();
  81.     }
  82.     private DiagnosticProperties(){} // for clone
  83.    
  84.     @Override
  85.     public DiagnosticProperties clone(){
  86.        
  87.         DiagnosticProperties dmNew = new DiagnosticProperties();
  88.        
  89.         if(this.defaultFunction!=null){
  90.             dmNew.defaultFunction = new String(this.defaultFunction);
  91.         }
  92.        
  93.         if(this.diagnosticProperties!=null && this.diagnosticProperties.size()>0){
  94.             dmNew.diagnosticProperties = new Properties();
  95.             Enumeration<Object> enKeys = this.diagnosticProperties.keys();
  96.             while (enKeys.hasMoreElements()) {
  97.                 Object objKey = (Object) enKeys.nextElement();
  98.                 Object objValue = this.diagnosticProperties.get(objKey);    
  99.                 dmNew.diagnosticProperties.put(objKey, objValue);
  100.             }
  101.         }
  102.        
  103.         dmNew.throwExceptionPlaceholderFailedResolution = this.throwExceptionPlaceholderFailedResolution;
  104.        
  105.         if(this.mappingFullCodeToFullString!=null && this.mappingFullCodeToFullString.size()>0){
  106.             dmNew.mappingFullCodeToFullString = new HashMap<>();
  107.             for (String key : this.mappingFullCodeToFullString.keySet()) {
  108.                 String value = this.mappingFullCodeToFullString.get(key);
  109.                 dmNew.mappingFullCodeToFullString.put(key, value);
  110.             }
  111.         }
  112.        
  113.         if(this.mappingFunctionToCode!=null && this.mappingFunctionToCode.size()>0){
  114.             dmNew.mappingFunctionToCode = new HashMap<>();
  115.             for (String key : this.mappingFunctionToCode.keySet()) {
  116.                 String value = this.mappingFunctionToCode.get(key);
  117.                 dmNew.mappingFunctionToCode.put(key, value);
  118.             }
  119.         }
  120.        
  121.         if(this.mappingSeverityToCode!=null && this.mappingSeverityToCode.size()>0){
  122.             dmNew.mappingSeverityToCode = new HashMap<LowSeverity, String>();
  123.             for (LowSeverity key : this.mappingSeverityToCode.keySet()) {
  124.                 String value = this.mappingSeverityToCode.get(key);
  125.                 dmNew.mappingSeverityToCode.put(key, value);
  126.             }
  127.         }
  128.        
  129.         if(this.mappingStringCodeToDiagnostic!=null && this.mappingStringCodeToDiagnostic.size()>0){
  130.             dmNew.mappingStringCodeToDiagnostic = new HashMap<String, DiagnosticInfo>();
  131.             for (String key : this.mappingStringCodeToDiagnostic.keySet()) {
  132.                 DiagnosticInfo value = this.mappingStringCodeToDiagnostic.get(key);
  133.                 dmNew.mappingStringCodeToDiagnostic.put(key, value);
  134.             }
  135.         }
  136.        
  137.         return dmNew;
  138.     }

  139.    
  140.     private void init() throws UtilsException{
  141.        
  142.         if(this.diagnosticProperties.containsKey(EMPTY)){
  143.             return;
  144.         }
  145.        
  146.         // default function
  147.         if(this.diagnosticProperties.containsKey(DEFAULT_FUNCTION)==false){
  148.             throw new UtilsException("Property ["+DEFAULT_FUNCTION+"] undefined");
  149.         }
  150.         this.defaultFunction = this.diagnosticProperties.getProperty(DEFAULT_FUNCTION).trim();
  151.        
  152.        
  153.         // default severity code prefix
  154.         LowSeverity [] s = LowSeverity.values();
  155.         for (int i = 0; i < s.length; i++) {
  156.             String key = DEFAULT_SEVERITY_CODE_PREFIX+s[i].name();
  157.             if(this.diagnosticProperties.containsKey(key)==false){
  158.                 throw new UtilsException("Property ["+key+"] undefined");
  159.             }
  160.             this.mappingSeverityToCode.put(s[i], this.diagnosticProperties.getProperty(key).trim());
  161.         }
  162.        
  163.         // Mapping function to code
  164.         Properties functionToCodeProperties = Utilities.readProperties(PREFIX_FUNCTION, this.diagnosticProperties);
  165.         if(functionToCodeProperties.size()<=0){
  166.             throw new UtilsException("Functions undefined");
  167.         }
  168.         Enumeration<?> enFunction = functionToCodeProperties.keys();
  169.         while (enFunction.hasMoreElements()) {
  170.             String function = (String) enFunction.nextElement();
  171.             String code = functionToCodeProperties.getProperty(function);
  172.             if(this.mappingFunctionToCode.containsKey(function)){
  173.                 throw new UtilsException("Function ["+function+"] already exists");
  174.             }
  175.             if(function.contains(".")){
  176.                 throw new UtilsException("Function ["+function+"] contain character '.' not permitted");
  177.             }
  178.             if(code==null || code.trim().equals("")){
  179.                 throw new UtilsException("Code for function ["+function+"] undefined");
  180.             }
  181.             code = code.trim();
  182.             if(this.mappingFunctionToCode.values().contains(code)){
  183.                 throw new UtilsException("Code ["+code+"] already used for other function");
  184.             }
  185.             this.mappingFunctionToCode.put(function, code);
  186.            
  187.            
  188.             // Mapping diagnostic for function
  189.             String diagnosticForFunctionPrefix = PREFIX_DIAGNOSTIC+function+".";
  190.             Properties diagnosticForFunctionProperties = Utilities.readProperties(diagnosticForFunctionPrefix, this.diagnosticProperties);
  191.             if(diagnosticForFunctionProperties.size()<=0){
  192.                 throw new UtilsException("Diagnostic for function ["+function+"] undefined");
  193.             }
  194.             Enumeration<?> enDiagnostic = diagnosticForFunctionProperties.keys();
  195.             while (enDiagnostic.hasMoreElements()) {
  196.                
  197.                 String diagnosticTmp = (String) enDiagnostic.nextElement();
  198.                 if(!diagnosticTmp.endsWith(SUFFIX_DIAGNOSTIC_CODE) &&
  199.                         !diagnosticTmp.endsWith(SUFFIX_DIAGNOSTIC_MESSAGE) &&
  200.                         !diagnosticTmp.endsWith(SUFFIX_DIAGNOSTIC_SEVERITY)){
  201.                     throw new UtilsException("Unexpected element ["+diagnosticForFunctionPrefix+diagnosticTmp+"]");
  202.                 }
  203.                 String diagnosticNameWithoutSuffix = null;
  204.                 if(diagnosticTmp.endsWith(SUFFIX_DIAGNOSTIC_CODE)){
  205.                     diagnosticNameWithoutSuffix = diagnosticTmp.substring(0, diagnosticTmp.length()-SUFFIX_DIAGNOSTIC_CODE.length());
  206.                 }
  207.                 else if(diagnosticTmp.endsWith(SUFFIX_DIAGNOSTIC_MESSAGE)){
  208.                     diagnosticNameWithoutSuffix = diagnosticTmp.substring(0, diagnosticTmp.length()-SUFFIX_DIAGNOSTIC_MESSAGE.length());
  209.                 }
  210.                 else if(diagnosticTmp.endsWith(SUFFIX_DIAGNOSTIC_SEVERITY)){
  211.                     diagnosticNameWithoutSuffix = diagnosticTmp.substring(0, diagnosticTmp.length()-SUFFIX_DIAGNOSTIC_SEVERITY.length());
  212.                 }
  213.                
  214.                 String valueTmp =  diagnosticForFunctionProperties.getProperty(diagnosticTmp);
  215.                 if(valueTmp==null || valueTmp.trim().equals("")){
  216.                     throw new UtilsException("Value for diagnostic ["+diagnosticForFunctionPrefix+diagnosticTmp+"] undefined");
  217.                 }
  218.                 valueTmp = valueTmp.trim();
  219.                
  220.                 String fullStringCode = function+"."+diagnosticNameWithoutSuffix;
  221.                 DiagnosticInfo diagInfo = null;
  222.                 if(this.mappingStringCodeToDiagnostic.containsKey(fullStringCode)){
  223.                     diagInfo = this.mappingStringCodeToDiagnostic.remove(fullStringCode);
  224.                 }
  225.                 else{
  226.                     diagInfo = new DiagnosticInfo();
  227.                     diagInfo.functionCode = code;
  228.                     diagInfo.functionString = function;
  229.                 }
  230.                 if(diagnosticTmp.endsWith(SUFFIX_DIAGNOSTIC_CODE)){
  231.                     if(diagInfo.code!=null){
  232.                         throw new UtilsException("Diagnostic ["+diagnosticForFunctionPrefix+diagnosticTmp+"] already defined");
  233.                     }
  234.                     diagInfo.code = valueTmp;
  235.                 }
  236.                 else if(diagnosticTmp.endsWith(SUFFIX_DIAGNOSTIC_MESSAGE)){
  237.                     if(diagInfo.message!=null){
  238.                         throw new UtilsException("Diagnostic ["+diagnosticForFunctionPrefix+diagnosticTmp+"] already defined");
  239.                     }
  240.                     diagInfo.message = valueTmp;
  241.                 }
  242.                 else if(diagnosticTmp.endsWith(SUFFIX_DIAGNOSTIC_SEVERITY)){
  243.                     if(diagInfo.severity!=null){
  244.                         throw new UtilsException("Diagnostic ["+diagnosticForFunctionPrefix+diagnosticTmp+"] already defined");
  245.                     }
  246.                     try{
  247.                         Severity severity = Severity.valueOf(valueTmp);
  248.                         diagInfo.severity = severity;
  249.                     }catch(Exception e){
  250.                         throw new UtilsException("Value for diagnostic ["+diagnosticForFunctionPrefix+diagnosticTmp+"] is not valid, expected: "+Arrays.asList(Severity.values()));
  251.                     }
  252.                 }
  253.                 this.mappingStringCodeToDiagnostic.put(fullStringCode, diagInfo);
  254.             }
  255.            
  256.         }
  257.        
  258.        
  259.         // Check ogni diagnostico abbia la tripla definita
  260.         for (String stringCode : this.mappingStringCodeToDiagnostic.keySet()) {
  261.             DiagnosticInfo diagInfo = this.mappingStringCodeToDiagnostic.get(stringCode);
  262.             if(diagInfo.code==null){
  263.                 throw new UtilsException("Undefined code for diagnostic ["+PREFIX_DIAGNOSTIC+stringCode+"]");
  264.             }
  265.             if(diagInfo.message==null){
  266.                 throw new UtilsException("Undefined message for diagnostic ["+PREFIX_DIAGNOSTIC+stringCode+"]");
  267.             }
  268.             if(diagInfo.severity==null){
  269.                 throw new UtilsException("Undefined severity for diagnostic ["+PREFIX_DIAGNOSTIC+stringCode+"]");
  270.             }
  271.             //System.out.println("REGISTER ["+diagInfo.functionCode+diagInfo.code+"]["+stringCode+"]");
  272.             this.mappingFullCodeToFullString.put(diagInfo.functionCode+diagInfo.code, stringCode);
  273.         }
  274.     }
  275.    
  276.     protected String getDefaultFunction() {
  277.         return this.defaultFunction;
  278.     }
  279.    
  280.     protected Map<String, String> getMappingFunctionToCode() {
  281.         return this.mappingFunctionToCode;
  282.     }
  283.     protected Map<String, String> getMappingFullCodeToFullString() {
  284.         return this.mappingFullCodeToFullString;
  285.     }
  286.     protected Map<String, DiagnosticInfo> getMappingStringCodeToDiagnostic() {
  287.         return this.mappingStringCodeToDiagnostic;
  288.     }
  289.     protected Map<LowSeverity, String> getMappingSeverityToCode() {
  290.         return this.mappingSeverityToCode;
  291.     }
  292.     protected boolean isThrowExceptionPlaceholderFailedResolution() {
  293.         return this.throwExceptionPlaceholderFailedResolution;
  294.     }
  295. }