DiagnosticManager.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.lang.reflect.Method;
  22. import java.text.SimpleDateFormat;
  23. import java.util.ArrayList;
  24. import java.util.Date;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Properties;

  28. import org.openspcoop2.utils.UtilsException;
  29. import org.openspcoop2.utils.date.DateUtils;
  30. import org.openspcoop2.utils.logger.constants.LowSeverity;
  31. import org.openspcoop2.utils.logger.constants.Severity;

  32. /**
  33.  * DiagnosticManager
  34.  *
  35.  * @author Poli Andrea (apoli@link.it)
  36.  * @author $Author$
  37.  * @version $Rev$, $Date$
  38.  */
  39. public class DiagnosticManager {
  40.        
  41.     private static final String CONTEXT = "context.";
  42.     private static final String DYNAMIC_OBJECT = "object.";
  43.    
  44.     private DiagnosticProperties diagnosticProperties;
  45.    
  46.     private IContext context;
  47.    
  48.     private ILogger loggerForCallback;
  49.    
  50.     protected DiagnosticManager(Properties diagnosticProperties, IContext context, boolean throwExceptionPlaceholderFailedResolution, ILogger loggerForCallback) throws UtilsException{
  51.         this.diagnosticProperties = DiagnosticProperties.getInstance(diagnosticProperties, throwExceptionPlaceholderFailedResolution);
  52.         this.context = context;
  53.        
  54.         this.loggerForCallback = loggerForCallback;

  55.     }
  56.     private DiagnosticManager(){} // for clone
  57.    
  58.     public DiagnosticManager clone(IContext newContext){
  59.        
  60.         DiagnosticManager dmNew = new DiagnosticManager();
  61.        
  62.         dmNew.context = newContext;
  63.        
  64.         dmNew.diagnosticProperties = this.diagnosticProperties.clone();
  65.                
  66.         dmNew.loggerForCallback = this.loggerForCallback;
  67.        
  68.         return dmNew;
  69.     }
  70.    
  71.     public List<String> getFunctions(){
  72.         List<String> keys = null;
  73.         if(!this.diagnosticProperties.getMappingFunctionToCode().isEmpty()) {
  74.             keys = new ArrayList<>();
  75.             for (String key : this.diagnosticProperties.getMappingFunctionToCode().keySet()) {
  76.                 keys.add(key);
  77.             }
  78.         }
  79.         return keys;
  80.     }
  81.    
  82.     public String getDefaultFunction() {
  83.         return this.diagnosticProperties.getDefaultFunction();
  84.     }
  85.    
  86.     public String getDefaultCode(String function, LowSeverity severity) throws UtilsException{
  87.         if(this.diagnosticProperties.getMappingFunctionToCode().containsKey(function)==false){
  88.             throw new UtilsException("Function ["+function+"] undefined");
  89.         }
  90.         return this.diagnosticProperties.getMappingFunctionToCode().get(function)  + this.diagnosticProperties.getMappingSeverityToCode().get(severity);
  91.     }
  92.    
  93.     public String getCode(String code) throws UtilsException{
  94.         if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
  95.             // è già il codice
  96.             return code;
  97.         }
  98.         if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
  99.             // è un codice stringa, ritorno il codice numerico
  100.             return this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(code).functionCode+this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(code).code;
  101.         }
  102.         throw new UtilsException("Diagnostic with code ["+code+"] undefined");
  103.     }
  104.    
  105.     public String getHumanCode(String code) throws UtilsException{
  106.         if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
  107.             // è già il codice human
  108.             return code;
  109.         }
  110.         if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
  111.             return this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
  112.         }
  113.         throw new UtilsException("Diagnostic with code ["+code+"] undefined");
  114.     }
  115.    
  116.     public Severity getSeverity(String code) throws UtilsException{
  117.         String codeString = null;
  118.         if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
  119.             codeString = this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
  120.         }
  121.         if(codeString==null){
  122.             if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
  123.                 // è gia codice stringa
  124.                 codeString = code;
  125.             }
  126.         }
  127.         if(codeString==null)
  128.             throw new UtilsException("Diagnostic with code ["+code+"] undefined");
  129.         return this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(codeString).severity;
  130.     }
  131.    
  132.     public String getMessage(String code, String ... params) throws UtilsException{
  133.         String codeString = null;
  134.         if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
  135.             codeString = this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
  136.         }
  137.         if(codeString==null){
  138.             if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
  139.                 // è gia codice stringa
  140.                 codeString = code;
  141.             }
  142.         }
  143.         if(codeString==null)
  144.             throw new UtilsException("Diagnostic with code ["+code+"] undefined");
  145.         return this.replacePlaceholders(code, this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(codeString).message,null,params);
  146.     }
  147.    
  148.     public String getMessage(String code, Object o) throws UtilsException{
  149.         String codeString = null;
  150.         if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
  151.             codeString = this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
  152.         }
  153.         if(codeString==null){
  154.             if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
  155.                 // è gia codice stringa
  156.                 codeString = code;
  157.             }
  158.         }
  159.         if(codeString==null)
  160.             throw new UtilsException("Diagnostic with code ["+code+"] undefined");
  161.         return this.replacePlaceholders(code, this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(codeString).message,o);
  162.     }
  163.    
  164.     public String getFunction(String code) throws UtilsException{
  165.         String codeString = null;
  166.         if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
  167.             codeString = this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
  168.         }
  169.         if(codeString==null){
  170.             if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
  171.                 // è gia codice stringa
  172.                 codeString = code;
  173.             }
  174.         }
  175.         if(codeString==null)
  176.             throw new UtilsException("Diagnostic with code ["+code+"] undefined");
  177.         return this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(codeString).functionString;
  178.        
  179.     }
  180.    
  181.    
  182.     private String replacePlaceholders(String diagnostic, String msg, Object dinamycObject, String ... params) throws UtilsException{
  183.        
  184.         /* Potenzialmente N^2  
  185.         String tmp = msg;
  186.         Enumeration<String> keys = this.keywordLogPersonalizzati.keys();
  187.         while(keys.hasMoreElements()){
  188.             String key = keys.nextElement();
  189.             tmp = tmp.replace(key, this.keywordLogPersonalizzati.get(key));
  190.         }
  191.         return tmp;
  192.         */
  193.        
  194.         // Check di esistenza di almeno 2 '${' e }
  195.         if(msg!=null && msg.length()>2){
  196.             int index1 = msg.indexOf("{");
  197.             int index2 = msg.indexOf("}",index1+1);
  198.             if(index1<0 || index2<0){
  199.                 return msg; // non serve il replace
  200.             }
  201.         }
  202.        
  203.         if(msg==null) {
  204.             return msg;
  205.         }
  206.        
  207.         StringBuilder bf = new StringBuilder();
  208.         StringBuilder keyword = new StringBuilder();
  209.         boolean separator = false;
  210.         for(int i=0; i<msg.length(); i++){
  211.             char ch = msg.charAt(i);
  212.             if( ('{' == ch) || ('}' == ch) ){
  213.                 //char separatorChar = ch;
  214.                 if(separator==false){
  215.                     // inizio keyword
  216.                     //keyword.append(separatorChar);
  217.                     separator = true;
  218.                 }
  219.                 else{
  220.                     // fine keyword
  221.                     //keyword.append(separatorChar);
  222.                     String valoreRimpiazzato = this.getValue(diagnostic, keyword.toString(), dinamycObject, params);
  223.                     if(valoreRimpiazzato==null){
  224.                         // keyword non esistente, devo utilizzare l'originale
  225.                         if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  226.                             throw new UtilsException("Placeholder [{"+keyword.toString()+"}] resolution failed");
  227.                         }
  228.                         else{
  229.                             //bf.append("{"+keyword.toString()+"}");
  230.                             bf.append("(???Placeholder ["+"{"+keyword.toString()+"] return null value)");
  231.                         }
  232.                     }else{
  233.                         bf.append(valoreRimpiazzato);
  234.                     }
  235.                     keyword.delete(0, keyword.length());
  236.                     separator=false;
  237.                 }
  238.             }else{
  239.                 if(separator){
  240.                     // sto scrivendo la keyword
  241.                     keyword.append(ch);
  242.                 }else{
  243.                     bf.append(ch);
  244.                 }
  245.             }
  246.         }
  247.         return bf.toString();
  248.     }
  249.    
  250.     private String getValue(String diagnostic, String key, Object dinamycObject, String ... params) throws UtilsException{
  251.         if(key.startsWith(CONTEXT)){
  252.             if(this.context==null){
  253.                 if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  254.                     throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] required context");
  255.                 }
  256.                 else{
  257.                     return "(???Placeholder ["+key+"] required context)";
  258.                 }
  259.             }
  260.             return this.readValueInObject(diagnostic, this.context, key.substring(CONTEXT.length(), key.length()), key);
  261.         }
  262.         else if(key.startsWith(DYNAMIC_OBJECT)){
  263.             if(dinamycObject==null){
  264.                 if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  265.                     throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] required dynamic parameter");
  266.                 }
  267.                 else{
  268.                     return "(???Placeholder ["+key+"] required dynamic parameter)";
  269.                 }
  270.             }
  271.             return this.readValueInObject(diagnostic, dinamycObject, key.substring(DYNAMIC_OBJECT.length(), key.length()), key);
  272.         }
  273.         else{
  274.             try{
  275.                 int intValue = Integer.parseInt(key);
  276.                 if(intValue<0){
  277.                     if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  278.                         throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] unsupported");
  279.                     }
  280.                     else{
  281.                         return "(???Placeholder ["+key+"] unsupported)";
  282.                     }
  283.                 }
  284.                 if(params==null || params.length<=0){
  285.                     if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  286.                         throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] required parameters");
  287.                     }
  288.                     else{
  289.                         return "(???Placeholder ["+key+"] required parameters)";
  290.                     }
  291.                 }
  292.                 if(intValue>=params.length){
  293.                     if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  294.                         throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] grather then parameters size:"+params.length);
  295.                     }
  296.                     else{
  297.                         return "(???Placeholder ["+key+"] grather then parameters size:"+params.length+")";
  298.                     }
  299.                 }
  300.                 return params[intValue];
  301.             }catch(Exception e){
  302.                 if(e instanceof UtilsException){
  303.                     throw (UtilsException) e;
  304.                 }
  305.                 else{
  306.                    
  307.                     // provo a chiamare callback
  308.                     try{
  309.                         if(this.loggerForCallback!=null){
  310.                             String value = this.loggerForCallback.getLogParam(key);
  311.                             if(value!=null){
  312.                                 return value;
  313.                             }
  314.                         }
  315.                     }catch(Exception eCallback){
  316.                         if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  317.                             throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] callback resolution failed: "+eCallback.getMessage(),eCallback);
  318.                         }
  319.                         else{
  320.                             return "(???Placeholder ["+key+"] callback resolution failed: "+eCallback.getMessage()+")";
  321.                         }
  322.                     }
  323.                    
  324.                     if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  325.                         throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] unsupported: "+e.getMessage(),e);
  326.                     }
  327.                     else{
  328.                         return "(???Placeholder ["+key+"] unsupported: "+e.getMessage()+")";
  329.                     }
  330.                 }
  331.             }
  332.         }
  333.     }
  334.     private String readValueInObject(String diagnostic, Object o,String name, String placeholderOriginale) throws UtilsException{
  335.         //System.out.println("Invocato con oggetto["+o.getClass().getName()+"] nome["+name+"]");
  336.         String fieldName = name;
  337.         String position = null;
  338.         if(name.contains(".")){
  339.             fieldName = name.substring(0, name.indexOf("."));
  340.         }
  341.         String methodName = new String(fieldName);
  342.         if(fieldName.endsWith("]") && fieldName.contains("[")){
  343.             try{
  344.                 position = fieldName.substring(fieldName.indexOf("[")+1,fieldName.length()-1);
  345.                 methodName = fieldName.substring(0, fieldName.indexOf("["));
  346.             }catch(Exception e){
  347.                 if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  348.                     throw new UtilsException("Errore durante l'identificazione del parametro di posizionamento ["+fieldName+"]: "+e.getMessage(),e);
  349.                 }
  350.                 else{
  351.                     return "(???Placeholder ["+placeholderOriginale+"] uncorrect, errore durante l'identificazione del parametro di posizionamento ["+fieldName+"]: "+e.getMessage()+")";
  352.                 }
  353.             }
  354.         }
  355.         //System.out.println("NAME ["+fieldName+"] position["+position+"]");
  356.         String getMethod = "get"+((methodName.charAt(0)+"").toUpperCase());
  357.         if(methodName.length()>1){
  358.             getMethod = getMethod + methodName.substring(1);
  359.         }
  360.         Method m = null;
  361.         try{
  362.             m = o.getClass().getMethod(getMethod);
  363.         }catch(Throwable e){
  364.             if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  365.                 throw new UtilsException("(diagnostic:"+diagnostic+") Method ["+o.getClass().getName()+"."+getMethod+"()] not found: "+e.getMessage(),e);
  366.             }
  367.             else{
  368.                 return "(???Placeholder ["+placeholderOriginale+"] Method ["+o.getClass().getName()+"."+getMethod+"()] not found: "+e.getMessage()+")";
  369.             }
  370.         }
  371.         Object ret = null;
  372.         try{
  373.             ret = m.invoke(o);
  374.         }catch(Throwable e){
  375.             if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  376.                 throw new UtilsException("(diagnostic:"+diagnostic+") Invocation method ["+o.getClass().getName()+"."+getMethod+"()] failed: "+e.getMessage(),e);
  377.             }
  378.             else{
  379.                 return "(???Placeholder ["+placeholderOriginale+"] Invocation method ["+o.getClass().getName()+"."+getMethod+"()] failed: "+e.getMessage()+")";
  380.             }
  381.         }
  382.         if(ret!=null){
  383.             if(ret instanceof List<?> || ret instanceof Map<?,?> || ret instanceof Object[]){
  384.                 if(position==null){
  385.                     if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  386.                         throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object without position");
  387.                     }
  388.                     else{
  389.                         return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object without position)";
  390.                     }
  391.                 }
  392.                 //System.out.println("ARRAY ["+ret.getClass().getName()+"]");
  393.                 if(ret instanceof List<?> || ret instanceof Object[]){
  394.                     int index = -1;
  395.                     try{
  396.                         index = Integer.parseInt(position);
  397.                     }catch(Exception e){
  398.                         if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  399.                             throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position value (not integer?): "+e.getMessage()+" )");
  400.                         }
  401.                         else{
  402.                             return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position value (not integer?): "+e.getMessage()+" )";
  403.                         }
  404.                     }
  405.                     if(ret instanceof List<?>){
  406.                         List<?> list = (List<?>) ret;
  407.                         if(list.size()<=index){
  408.                             if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  409.                                 throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position value "+index+" (list size:"+list.size()+") )");
  410.                             }
  411.                             else{
  412.                                 return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position value "+index+" (list size:"+list.size()+") )";
  413.                             }
  414.                         }
  415.                         ret = list.get(index);
  416.                     }
  417.                     else if(ret instanceof Object[]){
  418.                         Object[] arrayObj = (Object[]) ret;
  419.                         if(arrayObj.length<=index){
  420.                             if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  421.                                 throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position value "+index+" (array size:"+arrayObj.length+") )");
  422.                             }
  423.                             else{
  424.                                 return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position value "+index+" (array size:"+arrayObj.length+") )";
  425.                             }
  426.                         }
  427.                         ret = arrayObj[index];
  428.                     }
  429.                 }
  430.                 else if(ret instanceof Map<?,?>){
  431.                     Map<?,?> map = (Map<?,?>) ret;
  432.                     if(map.containsKey(position)==false){
  433.                         if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  434.                             throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position ["+position+"] not exists as key in map )");
  435.                         }
  436.                         else{
  437.                             return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position ["+position+"] not exists as key in map )";
  438.                         }
  439.                     }
  440.                     ret = map.get(position);
  441.                 }
  442.                
  443.                
  444.             }
  445.         }
  446.         if(name.contains(".")){
  447.             if(ret==null){
  448.                 if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  449.                     throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return null object");
  450.                 }
  451.                 else{
  452.                     return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return null object)";
  453.                 }
  454.             }
  455.             else{
  456.                 return this.readValueInObject(diagnostic, ret, name.substring((fieldName+".").length(), name.length()), placeholderOriginale);
  457.             }
  458.         }
  459.         else{
  460.             // finale
  461.             String finalValue = null;
  462.             if(ret!=null){
  463.                 if(ret instanceof Date){
  464.                     SimpleDateFormat dateformat = DateUtils.getSimpleDateFormatMs();
  465.                     finalValue = dateformat.format((Date)ret);
  466.                 }
  467.                 else if(ret instanceof byte[]){
  468.                     // 1024 = 1K
  469.                      // Visualizzo al massimo 5K
  470.                      int max = 5 * 1024;
  471.                      return org.openspcoop2.utils.Utilities.convertToPrintableText((byte[])ret, max);
  472.                 }
  473.                 else{
  474.                     finalValue = ret.toString();
  475.                 }
  476.             }
  477.             else{
  478.                 if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
  479.                     throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return null object");
  480.                 }
  481.                 else{
  482.                     return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return null object)";
  483.                 }
  484.             }
  485.             return finalValue;
  486.         }
  487.     }
  488.    
  489. }

  490. class DiagnosticInfo {
  491.    
  492.     String functionString;
  493.     String functionCode;
  494.     String code;
  495.     Severity severity;
  496.     String message;
  497.    
  498. }