DiagnosticManager.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.utils.logger;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.date.DateUtils;
import org.openspcoop2.utils.logger.constants.LowSeverity;
import org.openspcoop2.utils.logger.constants.Severity;
/**
* DiagnosticManager
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class DiagnosticManager {
private static final String CONTEXT = "context.";
private static final String DYNAMIC_OBJECT = "object.";
private DiagnosticProperties diagnosticProperties;
private IContext context;
private ILogger loggerForCallback;
protected DiagnosticManager(Properties diagnosticProperties, IContext context, boolean throwExceptionPlaceholderFailedResolution, ILogger loggerForCallback) throws UtilsException{
this.diagnosticProperties = DiagnosticProperties.getInstance(diagnosticProperties, throwExceptionPlaceholderFailedResolution);
this.context = context;
this.loggerForCallback = loggerForCallback;
}
private DiagnosticManager(){} // for clone
public DiagnosticManager clone(IContext newContext){
DiagnosticManager dmNew = new DiagnosticManager();
dmNew.context = newContext;
dmNew.diagnosticProperties = this.diagnosticProperties.clone();
dmNew.loggerForCallback = this.loggerForCallback;
return dmNew;
}
public List<String> getFunctions(){
List<String> keys = null;
if(!this.diagnosticProperties.getMappingFunctionToCode().isEmpty()) {
keys = new ArrayList<>();
for (String key : this.diagnosticProperties.getMappingFunctionToCode().keySet()) {
keys.add(key);
}
}
return keys;
}
public String getDefaultFunction() {
return this.diagnosticProperties.getDefaultFunction();
}
public String getDefaultCode(String function, LowSeverity severity) throws UtilsException{
if(this.diagnosticProperties.getMappingFunctionToCode().containsKey(function)==false){
throw new UtilsException("Function ["+function+"] undefined");
}
return this.diagnosticProperties.getMappingFunctionToCode().get(function) + this.diagnosticProperties.getMappingSeverityToCode().get(severity);
}
public String getCode(String code) throws UtilsException{
if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
// è già il codice
return code;
}
if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
// è un codice stringa, ritorno il codice numerico
return this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(code).functionCode+this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(code).code;
}
throw new UtilsException("Diagnostic with code ["+code+"] undefined");
}
public String getHumanCode(String code) throws UtilsException{
if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
// è già il codice human
return code;
}
if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
return this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
}
throw new UtilsException("Diagnostic with code ["+code+"] undefined");
}
public Severity getSeverity(String code) throws UtilsException{
String codeString = null;
if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
codeString = this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
}
if(codeString==null){
if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
// è gia codice stringa
codeString = code;
}
}
if(codeString==null)
throw new UtilsException("Diagnostic with code ["+code+"] undefined");
return this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(codeString).severity;
}
public String getMessage(String code, String ... params) throws UtilsException{
String codeString = null;
if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
codeString = this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
}
if(codeString==null){
if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
// è gia codice stringa
codeString = code;
}
}
if(codeString==null)
throw new UtilsException("Diagnostic with code ["+code+"] undefined");
return this.replacePlaceholders(code, this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(codeString).message,null,params);
}
public String getMessage(String code, Object o) throws UtilsException{
String codeString = null;
if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
codeString = this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
}
if(codeString==null){
if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
// è gia codice stringa
codeString = code;
}
}
if(codeString==null)
throw new UtilsException("Diagnostic with code ["+code+"] undefined");
return this.replacePlaceholders(code, this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(codeString).message,o);
}
public String getFunction(String code) throws UtilsException{
String codeString = null;
if(this.diagnosticProperties.getMappingFullCodeToFullString().containsKey(code)){
codeString = this.diagnosticProperties.getMappingFullCodeToFullString().get(code);
}
if(codeString==null){
if(this.diagnosticProperties.getMappingStringCodeToDiagnostic().containsKey(code)){
// è gia codice stringa
codeString = code;
}
}
if(codeString==null)
throw new UtilsException("Diagnostic with code ["+code+"] undefined");
return this.diagnosticProperties.getMappingStringCodeToDiagnostic().get(codeString).functionString;
}
private String replacePlaceholders(String diagnostic, String msg, Object dinamycObject, String ... params) throws UtilsException{
/* Potenzialmente N^2
String tmp = msg;
Enumeration<String> keys = this.keywordLogPersonalizzati.keys();
while(keys.hasMoreElements()){
String key = keys.nextElement();
tmp = tmp.replace(key, this.keywordLogPersonalizzati.get(key));
}
return tmp;
*/
// Check di esistenza di almeno 2 '${' e }
if(msg!=null && msg.length()>2){
int index1 = msg.indexOf("{");
int index2 = msg.indexOf("}",index1+1);
if(index1<0 || index2<0){
return msg; // non serve il replace
}
}
if(msg==null) {
return msg;
}
StringBuilder bf = new StringBuilder();
StringBuilder keyword = new StringBuilder();
boolean separator = false;
for(int i=0; i<msg.length(); i++){
char ch = msg.charAt(i);
if( ('{' == ch) || ('}' == ch) ){
//char separatorChar = ch;
if(separator==false){
// inizio keyword
//keyword.append(separatorChar);
separator = true;
}
else{
// fine keyword
//keyword.append(separatorChar);
String valoreRimpiazzato = this.getValue(diagnostic, keyword.toString(), dinamycObject, params);
if(valoreRimpiazzato==null){
// keyword non esistente, devo utilizzare l'originale
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("Placeholder [{"+keyword.toString()+"}] resolution failed");
}
else{
//bf.append("{"+keyword.toString()+"}");
bf.append("(???Placeholder ["+"{"+keyword.toString()+"] return null value)");
}
}else{
bf.append(valoreRimpiazzato);
}
keyword.delete(0, keyword.length());
separator=false;
}
}else{
if(separator){
// sto scrivendo la keyword
keyword.append(ch);
}else{
bf.append(ch);
}
}
}
return bf.toString();
}
private String getValue(String diagnostic, String key, Object dinamycObject, String ... params) throws UtilsException{
if(key.startsWith(CONTEXT)){
if(this.context==null){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] required context");
}
else{
return "(???Placeholder ["+key+"] required context)";
}
}
return this.readValueInObject(diagnostic, this.context, key.substring(CONTEXT.length(), key.length()), key);
}
else if(key.startsWith(DYNAMIC_OBJECT)){
if(dinamycObject==null){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] required dynamic parameter");
}
else{
return "(???Placeholder ["+key+"] required dynamic parameter)";
}
}
return this.readValueInObject(diagnostic, dinamycObject, key.substring(DYNAMIC_OBJECT.length(), key.length()), key);
}
else{
try{
int intValue = Integer.parseInt(key);
if(intValue<0){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] unsupported");
}
else{
return "(???Placeholder ["+key+"] unsupported)";
}
}
if(params==null || params.length<=0){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] required parameters");
}
else{
return "(???Placeholder ["+key+"] required parameters)";
}
}
if(intValue>=params.length){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] grather then parameters size:"+params.length);
}
else{
return "(???Placeholder ["+key+"] grather then parameters size:"+params.length+")";
}
}
return params[intValue];
}catch(Exception e){
if(e instanceof UtilsException){
throw (UtilsException) e;
}
else{
// provo a chiamare callback
try{
if(this.loggerForCallback!=null){
String value = this.loggerForCallback.getLogParam(key);
if(value!=null){
return value;
}
}
}catch(Exception eCallback){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] callback resolution failed: "+eCallback.getMessage(),eCallback);
}
else{
return "(???Placeholder ["+key+"] callback resolution failed: "+eCallback.getMessage()+")";
}
}
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+key+"] unsupported: "+e.getMessage(),e);
}
else{
return "(???Placeholder ["+key+"] unsupported: "+e.getMessage()+")";
}
}
}
}
}
private String readValueInObject(String diagnostic, Object o,String name, String placeholderOriginale) throws UtilsException{
//System.out.println("Invocato con oggetto["+o.getClass().getName()+"] nome["+name+"]");
String fieldName = name;
String position = null;
if(name.contains(".")){
fieldName = name.substring(0, name.indexOf("."));
}
String methodName = new String(fieldName);
if(fieldName.endsWith("]") && fieldName.contains("[")){
try{
position = fieldName.substring(fieldName.indexOf("[")+1,fieldName.length()-1);
methodName = fieldName.substring(0, fieldName.indexOf("["));
}catch(Exception e){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("Errore durante l'identificazione del parametro di posizionamento ["+fieldName+"]: "+e.getMessage(),e);
}
else{
return "(???Placeholder ["+placeholderOriginale+"] uncorrect, errore durante l'identificazione del parametro di posizionamento ["+fieldName+"]: "+e.getMessage()+")";
}
}
}
//System.out.println("NAME ["+fieldName+"] position["+position+"]");
String getMethod = "get"+((methodName.charAt(0)+"").toUpperCase());
if(methodName.length()>1){
getMethod = getMethod + methodName.substring(1);
}
Method m = null;
try{
m = o.getClass().getMethod(getMethod);
}catch(Throwable e){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Method ["+o.getClass().getName()+"."+getMethod+"()] not found: "+e.getMessage(),e);
}
else{
return "(???Placeholder ["+placeholderOriginale+"] Method ["+o.getClass().getName()+"."+getMethod+"()] not found: "+e.getMessage()+")";
}
}
Object ret = null;
try{
ret = m.invoke(o);
}catch(Throwable e){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Invocation method ["+o.getClass().getName()+"."+getMethod+"()] failed: "+e.getMessage(),e);
}
else{
return "(???Placeholder ["+placeholderOriginale+"] Invocation method ["+o.getClass().getName()+"."+getMethod+"()] failed: "+e.getMessage()+")";
}
}
if(ret!=null){
if(ret instanceof List<?> || ret instanceof Map<?,?> || ret instanceof Object[]){
if(position==null){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object without position");
}
else{
return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object without position)";
}
}
//System.out.println("ARRAY ["+ret.getClass().getName()+"]");
if(ret instanceof List<?> || ret instanceof Object[]){
int index = -1;
try{
index = Integer.parseInt(position);
}catch(Exception e){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
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()+" )");
}
else{
return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position value (not integer?): "+e.getMessage()+" )";
}
}
if(ret instanceof List<?>){
List<?> list = (List<?>) ret;
if(list.size()<=index){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
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()+") )");
}
else{
return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position value "+index+" (list size:"+list.size()+") )";
}
}
ret = list.get(index);
}
else if(ret instanceof Object[]){
Object[] arrayObj = (Object[]) ret;
if(arrayObj.length<=index){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
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+") )");
}
else{
return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position value "+index+" (array size:"+arrayObj.length+") )";
}
}
ret = arrayObj[index];
}
}
else if(ret instanceof Map<?,?>){
Map<?,?> map = (Map<?,?>) ret;
if(map.containsKey(position)==false){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
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 )");
}
else{
return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return "+ret.getClass().getName()+" object, wrong position ["+position+"] not exists as key in map )";
}
}
ret = map.get(position);
}
}
}
if(name.contains(".")){
if(ret==null){
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return null object");
}
else{
return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return null object)";
}
}
else{
return this.readValueInObject(diagnostic, ret, name.substring((fieldName+".").length(), name.length()), placeholderOriginale);
}
}
else{
// finale
String finalValue = null;
if(ret!=null){
if(ret instanceof Date){
SimpleDateFormat dateformat = DateUtils.getSimpleDateFormatMs();
finalValue = dateformat.format((Date)ret);
}
else if(ret instanceof byte[]){
// 1024 = 1K
// Visualizzo al massimo 5K
int max = 5 * 1024;
return org.openspcoop2.utils.Utilities.convertToPrintableText((byte[])ret, max);
}
else{
finalValue = ret.toString();
}
}
else{
if(this.diagnosticProperties.isThrowExceptionPlaceholderFailedResolution()){
throw new UtilsException("(diagnostic:"+diagnostic+") Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return null object");
}
else{
return "(???Placeholder ["+placeholderOriginale+"] uncorrect, method ["+o.getClass().getName()+"."+getMethod+"()] return null object)";
}
}
return finalValue;
}
}
}
class DiagnosticInfo {
String functionString;
String functionCode;
String code;
Severity severity;
String message;
}