LoggerWrapperFactory.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;

  21. import java.io.File;
  22. import java.io.FileOutputStream;
  23. import java.net.URI;
  24. import java.net.URISyntaxException;
  25. import java.net.URL;
  26. import java.nio.file.Files;
  27. import java.nio.file.Path;
  28. import java.util.HashSet;
  29. import java.util.Iterator;
  30. import java.util.List;
  31. import java.util.Map;
  32. import java.util.Objects;
  33. import java.util.Properties;
  34. import java.util.Set;
  35. import java.util.regex.Matcher;
  36. import java.util.regex.Pattern;
  37. import java.util.stream.Collectors;

  38. import org.apache.commons.lang.StringUtils;
  39. import org.apache.logging.log4j.Level;
  40. import org.apache.logging.log4j.LogManager;
  41. import org.apache.logging.log4j.core.Appender;
  42. import org.apache.logging.log4j.core.LoggerContext;
  43. import org.apache.logging.log4j.core.appender.ConsoleAppender;
  44. import org.apache.logging.log4j.core.config.Configuration;
  45. import org.apache.logging.log4j.core.config.ConfigurationFactory;
  46. import org.apache.logging.log4j.core.config.Configurator;
  47. import org.apache.logging.log4j.core.config.LoggerConfig;
  48. import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
  49. import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
  50. import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
  51. import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
  52. import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
  53. import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
  54. import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
  55. import org.apache.logging.log4j.core.config.json.JsonConfigurationFactory;
  56. import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory;
  57. import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;
  58. import org.apache.logging.log4j.core.config.yaml.YamlConfigurationFactory;

  59. /**
  60.  * Libreria contenente metodi di utilità per gestire i log con log4j2
  61.  *
  62.  *
  63.  * @author Poli Andrea (apoli@link.it)
  64.  * @author Tommaso Burlon (tommaso.burlon@link.it)
  65.  * @author $Author$
  66.  * @version $Rev$, $Date$
  67.  */
  68. public class LoggerWrapperFactory {
  69.    
  70.     private LoggerWrapperFactory () {}

  71.    
  72.    
  73.     // ** Ritorna il logger */
  74.    
  75.     // NAME[org.apache.logging.slf4j.Log4jLogger] FACT[org.apache.logging.slf4j.Log4jLoggerFactory]
  76.     // I valori sopra sono se si possiede un corretto binding di log4j su slf.
  77.     // Se esistono più jar contenenti l'implementazione di un binding, non è detto che venga preso log4j.
  78.    
  79.     public static org.slf4j.Logger getLogger(Class<?> c){
  80.         return org.slf4j.LoggerFactory.getLogger(c);
  81.     }
  82.     public static org.slf4j.Logger getLogger(String name){
  83.         return org.slf4j.LoggerFactory.getLogger(name);
  84.     }
  85.     public static org.apache.logging.log4j.Logger getLoggerImpl(Class<?> c){
  86.         return org.apache.logging.log4j.LogManager.getLogger(c);
  87.     }
  88.     public static org.apache.logging.log4j.Logger getLoggerImpl(String name){
  89.         return org.apache.logging.log4j.LogManager.getLogger(name);
  90.     }
  91.    
  92.    
  93.    
  94.    
  95.     // ** Imposta tipo di ConnectionFactory (Default is xml) */
  96.    
  97.     public static void setPropertiesConfigurationFactory(){
  98.         ConfigurationFactory.setConfigurationFactory(new PropertiesConfigurationFactory());
  99.     }
  100.     public static void setJSonConfigurationFactory(){
  101.         ConfigurationFactory.setConfigurationFactory(new JsonConfigurationFactory());
  102.     }
  103.     public static void setXmlConfigurationFactory(){
  104.         ConfigurationFactory.setConfigurationFactory(new XmlConfigurationFactory());
  105.     }
  106.     public static void setYamlConfigurationFactory(){
  107.         ConfigurationFactory.setConfigurationFactory(new YamlConfigurationFactory());
  108.     }
  109.    
  110.    
  111.    
  112.    
  113.     // ** Ritorna Context log4J2 */
  114.    
  115.     private static LoggerContext getContext(){
  116.         return (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
  117.     }
  118.     @SuppressWarnings("unused")
  119.     private static LoggerContext getContext(boolean currentContext){
  120.         return (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(currentContext);
  121.     }
  122.    

  123.     // ** Imposta proprietà in configurazione log4J2 */
  124.    
  125.     private static final String FORMAT_MSG = "%p <%d{dd-MM-yyyy HH:mm:ss.SSS}> %C.%M(%L): %m %n %n";
  126.    
  127.     public static void setDefaultConsoleLogConfiguration(Level level) {
  128.         setDefaultLogConfiguration(level, true, FORMAT_MSG, null, null);
  129.     }
  130.     public static void setDefaultConsoleLogConfiguration(Level level,
  131.             String layout) {
  132.         setDefaultLogConfiguration(level, true, layout, null, null);
  133.     }
  134.     public static void setDefaultLogConfiguration(Level level,boolean console,String layoutConsole,
  135.             File file,String layoutFile) {
  136.        
  137.         if(layoutConsole==null){
  138.             layoutConsole=FORMAT_MSG;
  139.         }
  140.         if(layoutFile==null){
  141.             layoutFile=FORMAT_MSG;
  142.         }
  143.        
  144.         ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
  145.         builder.setConfigurationName("ConsoleDefault");
  146.         builder.setStatusLevel(Level.ERROR);
  147.         // Console Appender
  148.         if(console){
  149.             AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").
  150.                     addAttribute("target",  ConsoleAppender.Target.SYSTEM_OUT);
  151.             appenderBuilder.add(builder.newLayout("PatternLayout")
  152.                     .addAttribute("pattern", layoutConsole));
  153.             builder.add(appenderBuilder);
  154.         }
  155.         if(file!=null){
  156.             // create a rolling file appender
  157.             LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
  158.                 .addAttribute("pattern", layoutFile);
  159.             ComponentBuilder<?> triggeringPolicy = builder.newComponent("Policies")
  160.                 .addComponent(builder.newComponent("CronTriggeringPolicy").addAttribute("schedule", "0 0 0 * * ?"))
  161.                 .addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "100M"));
  162.             AppenderComponentBuilder appenderBuilder = builder.newAppender("rolling", "RollingFile")
  163.                 .addAttribute("fileName", file.getAbsolutePath())
  164.                 .addAttribute("filePattern", file.getAbsolutePath()+".%i")
  165.                 .add(layoutBuilder)
  166.                 .addComponent(triggeringPolicy);
  167.             builder.add(appenderBuilder);
  168.         }
  169.         // RootLogger
  170.         RootLoggerComponentBuilder rootLoggerBuilder = builder.newRootLogger(level);
  171.         if(console){
  172.             rootLoggerBuilder.add(builder.newAppenderRef("Stdout"));
  173.         }
  174.         if(file!=null){
  175.             rootLoggerBuilder.add(builder.newAppenderRef("rolling"));
  176.         }
  177.         builder.add(rootLoggerBuilder);
  178.         // Initialize
  179.         Configurator.initialize(builder.build());
  180.     }
  181.    
  182.     public static void setLogConfiguration(File file) throws UtilsException{
  183.         setLogConfiguration(getContext(), file, false);
  184.     }
  185.     public static void setLogConfiguration(File file,boolean append) throws UtilsException{
  186.         setLogConfiguration(getContext(), file, append);
  187.     }
  188.     private static void setLogConfiguration(LoggerContext context, File file,boolean append) throws UtilsException{
  189.         String filePath = "fs";
  190.         try{
  191.             if(file==null){
  192.                 throw new UtilsException("Resource file undefined");
  193.             }
  194.             filePath = file.getAbsolutePath();
  195.             if(file.exists()){
  196.                 if(append){
  197.                     appendConfiguration(context, file.toURI());
  198.                 }
  199.                 else{
  200.                     newConfiguration(context, file.toURI());
  201.                 }
  202.             }
  203.             else{
  204.                 throw new UtilsException("Resource not exists");
  205.             }
  206.         }catch(Exception e){
  207.             throw new UtilsException("Setting Logging Configuration (resource ["+filePath+"]): "+e.getMessage(),e);
  208.         }
  209.     }
  210.     public static void setLogConfiguration(String name) throws UtilsException{
  211.         setLogConfiguration(getContext(), name, false);
  212.     }
  213.     public static void setLogConfiguration(String name,boolean append) throws UtilsException{
  214.         setLogConfiguration(getContext(), name, append);
  215.     }
  216.     private static void setLogConfiguration(LoggerContext context, String name,boolean append) throws UtilsException{
  217.         try{
  218.             if(name==null){
  219.                 throw new UtilsException("Resource name undefined");
  220.             }
  221.             File f = new File(name);
  222.             setLogConfiguration(context, name, append, f);
  223.         }catch(Exception e){
  224.             throw new UtilsException("Setting Logging Configuration failed (resource ["+name+"]): "+e.getMessage(),e);
  225.         }
  226.     }
  227.     private static void setLogConfiguration(LoggerContext context, String name,boolean append, File f) throws UtilsException, URISyntaxException{
  228.         if(f.exists()){
  229.             if(append){
  230.                 appendConfiguration(context, f.toURI());
  231.             }
  232.             else{
  233.                 newConfiguration(context, f.toURI());
  234.             }
  235.         }
  236.         else{
  237.             String newName = null;
  238.             if(name.trim().startsWith("/")){
  239.                 newName = name;
  240.             }
  241.             else{
  242.                 newName = "/" + name;
  243.             }
  244.             URL url = Utilities.class.getResource(newName);
  245.             if(url!=null){
  246.                 if(append){
  247.                     appendConfiguration(context, url.toURI());
  248.                 }
  249.                 else{
  250.                     newConfiguration(context, url.toURI());
  251.                 }
  252.             }
  253.             else{
  254.                 throw new UtilsException("Resource ["+name+"] not found");
  255.             }
  256.         }
  257.     }
  258.     public static void setLogConfiguration(URL url) throws UtilsException{
  259.         setLogConfiguration(getContext(), url, false);
  260.     }
  261.     public static void setLogConfiguration(URL url,boolean append) throws UtilsException{
  262.         setLogConfiguration(getContext(), url, append);
  263.     }
  264.     private static void setLogConfiguration(LoggerContext context, URL url,boolean append) throws UtilsException{
  265.         try{
  266.             if(url==null){
  267.                 throw new UtilsException("Resource URL undefined");
  268.             }
  269.             if(append){
  270.                 appendConfiguration(context, url.toURI());
  271.             }
  272.             else{
  273.                 newConfiguration(context, url.toURI());
  274.             }
  275.         }catch(Exception e){
  276.             throw new UtilsException("Setting Logging Configuration failed (url ["+url+"]): "+e.getMessage(),e);
  277.         }
  278.     }
  279.     public static void setLogConfiguration(URI uri) throws UtilsException{
  280.         setLogConfiguration(getContext(), uri, false);
  281.     }
  282.     public static void setLogConfiguration(URI uri,boolean append) throws UtilsException{
  283.         setLogConfiguration(getContext(), uri, append);
  284.     }
  285.     private static void setLogConfiguration(LoggerContext context, URI uri,boolean append) throws UtilsException{
  286.         try{
  287.             if(uri==null){
  288.                 throw new UtilsException("Resource URI undefined");
  289.             }
  290.             if(append){
  291.                 appendConfiguration(context, uri);
  292.             }
  293.             else{
  294.                 newConfiguration(context, uri);
  295.             }
  296.         }catch(Exception e){
  297.             throw new UtilsException("Setting Logging Configuration failed (uri ["+uri+"]): "+e.getMessage(),e);
  298.         }
  299.     }
  300.     public static void setLogConfiguration(Properties props) throws UtilsException{
  301.         setLogConfiguration(getContext(), props, false);
  302.     }
  303.     public static void setLogConfiguration(Properties props,boolean append) throws UtilsException{
  304.         setLogConfiguration(getContext(), props, append);
  305.     }
  306.     private static void setLogConfiguration(LoggerContext context, Properties props,boolean append) throws UtilsException{
  307.         if(props==null){
  308.             throw new UtilsException("Resource Properties undefined");
  309.         }
  310.        
  311.         File fTmp = null;
  312.         try {
  313.             fTmp = Utilities.createTempPath("op2_log", ".properties").toFile();
  314.         }catch(Exception e){
  315.             throw new UtilsException("Setting Logging Configuration failed: "+e.getMessage(),e);
  316.         }
  317.        
  318.         try(FileOutputStream foutTmp = new FileOutputStream(fTmp);){
  319.             props.store(foutTmp, "Tmp Configuration");
  320.             foutTmp.flush();
  321.            
  322.             if(append){
  323.                 appendConfiguration(context, fTmp.toURI());
  324.             }
  325.             else{
  326.                 newConfiguration(context, fTmp.toURI());
  327.             }
  328.            
  329.         }catch(Exception e){
  330.             throw new UtilsException("Setting Logging Configuration failed: "+e.getMessage(),e);
  331.         }finally{
  332.             try{
  333.                 if(fTmp!=null){
  334.                     Files.delete(fTmp.toPath());
  335.                 }
  336.             }catch(Exception e){
  337.                 // close
  338.             }
  339.         }
  340.     }

  341.    
  342.     private static void newConfiguration(LoggerContext context, URI configUri) {
  343.         context.setConfigLocation(configUri);
  344.     }
  345.     private static synchronized void appendConfiguration(LoggerContext context, URI configUri) {
  346.        
  347.         /**System.out.println("APPEND LOG ["+configUri+"]");*/
  348.        
  349.         Configuration actualConfiguration = context.getConfiguration();
  350.        
  351.         ConfigurationFactory configurationFactory = ConfigurationFactory.getInstance();
  352.         Configuration appendConfiguration = configurationFactory.getConfiguration(new LoggerContext(actualConfiguration.getName()), actualConfiguration.getName(), configUri);
  353.         appendConfiguration.initialize();
  354.        
  355.         Map<String, Appender> mapAppenders = appendConfiguration.getAppenders();
  356.         if(mapAppenders.size()>0){
  357.             Iterator<String> appenderNameIterator = mapAppenders.keySet().iterator();
  358.             while (appenderNameIterator.hasNext()) {
  359.                 String appenderName = appenderNameIterator.next();
  360.                 Appender appender = mapAppenders.get(appenderName);
  361.                 appender.start();
  362.                 /**System.out.println("ADD APPENDER ["+appenderName+"]");*/
  363.                 actualConfiguration.addAppender(appender);
  364.             }
  365.         }
  366.        
  367.         Map<String, LoggerConfig> mapLoggers = appendConfiguration.getLoggers();
  368.         if(mapLoggers.size()>0){
  369.             Iterator<String> loggerNameIterator = mapLoggers.keySet().iterator();
  370.             while (loggerNameIterator.hasNext()) {
  371.                 String loggerName = loggerNameIterator.next();              
  372.                 LoggerConfig logger = mapLoggers.get(loggerName);
  373.                 /**System.out.println("ADD LOGGER ["+loggerName+"]");*/
  374.                 actualConfiguration.addLogger(loggerName, logger);
  375.             }
  376.         }
  377.        
  378.         /**System.out.println("APPEND LOG ["+configUri+"] FINE");*/
  379.        
  380.     }
  381.    
  382.    
  383.     private static String readProperty(Properties loggerProperties,
  384.             String propName, Map<String, String> applicationEnv, String defaultValue) {
  385.         String value = System.getenv(applicationEnv.get(propName));
  386.         if (value != null && StringUtils.isNotEmpty(value))
  387.             return value;
  388.        
  389.         value = System.getenv(Costanti.ENV_LOG.get(propName));
  390.         if (value != null && StringUtils.isNotEmpty(value))
  391.             return value;
  392.        
  393.         value = System.getProperty(applicationEnv.get(propName));
  394.         if (value != null && StringUtils.isNotEmpty(value))
  395.             return value;
  396.        
  397.         value = System.getProperty(Costanti.ENV_LOG.get(propName));
  398.         if (value != null && StringUtils.isNotEmpty(value))
  399.             return value;
  400.        
  401.         value = loggerProperties.getProperty(propName);
  402.         if (value != null && StringUtils.isNotEmpty(value))
  403.             return value.trim();
  404.        
  405.         return defaultValue;
  406.     }
  407.    
  408.     private static final String LOGGER_CATEGORY_NAME_SUFFIX = ".name";
  409.    
  410.     private static Set<String> getLoggersIdByName(Properties loggerProperties, List<String> loggerNames) {
  411.         Set<String> enabledLoggers = new HashSet<>(loggerNames);
  412.         Set<String> loggersId = new HashSet<>();
  413.         boolean enabledAll = enabledLoggers.contains(Boolean.TRUE.toString());
  414.        
  415.         if (enabledLoggers.contains(Boolean.FALSE.toString()) && enabledLoggers.size() == 1)
  416.             return loggersId;
  417.        
  418.         for (Map.Entry<Object, Object> p : loggerProperties.entrySet()) {
  419.             String key = p.getKey().toString().trim();
  420.            
  421.            
  422.             if (key.startsWith("logger.") && key.endsWith(LOGGER_CATEGORY_NAME_SUFFIX)) {
  423.                 String value = p.getValue().toString().trim();
  424.                
  425.                 if (enabledAll || enabledLoggers.contains(value)) {
  426.                     String loggerId = key.substring(0, key.length() - LOGGER_CATEGORY_NAME_SUFFIX.length());
  427.                     loggersId.add(loggerId);
  428.                 }
  429.             }
  430.         }
  431.        
  432.         return loggersId;
  433.     }
  434.    
  435.     private static Set<String> getLoggersIdByName(Properties loggerProperties, String propName, Map<String, String> applicationEnv) {
  436.         List<String> enabledList = List.of(readProperty(loggerProperties, propName, applicationEnv, "false").split(","));
  437.         enabledList = enabledList.stream().map(String::trim).collect(Collectors.toList());
  438.         return getLoggersIdByName(loggerProperties, enabledList);
  439.     }
  440.    
  441.     private static final String LOGGER_APPENDER_PREFIX = "appender.";
  442.     private static final String LOGGER_APPENDER_NAME_SUFFIX = ".name";
  443.    
  444.     private static Set<String> getAppendersIdByName(Properties loggerProperties, Set<String> appenderNames) {
  445.         Set<String> appenderIds = new HashSet<>();
  446.         for (Map.Entry<Object, Object> p : loggerProperties.entrySet()) {
  447.             String key = p.getKey().toString().trim();
  448.            
  449.            
  450.             if (key.startsWith(LOGGER_APPENDER_PREFIX)
  451.                     && key.endsWith(LOGGER_APPENDER_NAME_SUFFIX)
  452.                     && appenderNames.contains(p.getValue().toString().trim())) {
  453.                
  454.                     String appenderId = key.substring(0, key.length() - LOGGER_APPENDER_NAME_SUFFIX.length());
  455.                     appenderIds.add(appenderId);
  456.                 }
  457.            
  458.         }
  459.        
  460.         return appenderIds;
  461.     }
  462.    
  463.     private static Set<String> getAppenderIdByLoggerName(Properties loggerProperties, String propName, Map<String, String> applicationEnv) {
  464.         Set<String> loggerIds = getLoggersIdByName(loggerProperties, propName, applicationEnv);
  465.         Set<String> appenderNames = new HashSet<>();
  466.        
  467.         if (loggerIds.isEmpty())
  468.             return Set.of();
  469.        
  470.         for (Map.Entry<Object, Object> p : loggerProperties.entrySet()) {
  471.             String key = p.getKey().toString().trim();
  472.            
  473.            
  474.             if (key.startsWith("logger.") && key.endsWith(".ref")) {
  475.                 String loggerId = key.substring(0, key.indexOf(".appenderRef"));
  476.                 if (loggerIds.contains(loggerId)) {
  477.                     appenderNames.add(p.getValue().toString().trim());
  478.                 }
  479.             }
  480.         }
  481.        
  482.         return getAppendersIdByName(loggerProperties, appenderNames);
  483.     }
  484.    
  485.    
  486.     /**
  487.      * Applica le patch necessarie per far utilizzare ai logger indicati lo stdout come appender
  488.      * @param loggerProperties
  489.      * @param applicationEnv
  490.      * @param vars
  491.      * @return
  492.      */
  493.     private static final Pattern LOG_VARIABLE_PATTERN = Pattern.compile("%\\{([^\\}]+)\\}");
  494.     private static Properties patchLoggersStdout(Properties loggerProperties, Map<String, String> applicationEnv, Map<String, String> vars) {
  495.         Set<String> loggerIds = getLoggersIdByName(loggerProperties,
  496.                 Costanti.PROP_ENABLE_STDOUT,
  497.                 applicationEnv);
  498.        
  499.         for (String loggerId : loggerIds) {
  500.             loggerProperties.put(loggerId + ".appenderRef.stdout.ref", "STDOUT");
  501.         }
  502.        
  503.         for (Map.Entry<Object, Object> p : loggerProperties.entrySet()) {
  504.             String key = p.getKey().toString().trim();
  505.             if (key.startsWith(LOGGER_APPENDER_PREFIX)
  506.                     && key.endsWith(LAYOUT_PATTERN_SUFFIX)) {
  507.                 String value = p.getValue().toString().trim();
  508.                 Matcher matcher = LOG_VARIABLE_PATTERN.matcher(value);
  509.                
  510.                 value = matcher.replaceAll(m -> {
  511.                     String out = vars.get(m.group(1).trim());
  512.                     return Objects.requireNonNullElse(out, m.group());
  513.                 });
  514.                
  515.                 p.setValue(value);
  516.             }
  517.            
  518.         }
  519.        
  520.         return loggerProperties;
  521.     }
  522.    
  523.     private static final String LAYOUT_TYPE_SUFFIX = ".layout.type";
  524.     private static final String LAYOUT_PATTERN_SUFFIX= ".layout.pattern";
  525.     private static final String LAYOUT_EVENT_TEMPLATE_URI_SUFFIX= ".layout.eventTemplateUri";
  526.    
  527.     /**
  528.      * Applica le patch necessarie per formattare in JSON l'output dei vari logger indicati
  529.      * @param loggerProperties
  530.      * @param applicationEnv
  531.      * @param vars
  532.      * @return
  533.      */
  534.     private static Properties patchLoggersJSON(Properties loggerProperties, Map<String, String> applicationEnv, Map<String, String> vars) {
  535.         Set<String> appenderIds = getAppenderIdByLoggerName(
  536.                 loggerProperties,
  537.                 Costanti.PROP_ENABLE_JSON,
  538.                 applicationEnv);
  539.        
  540.         String jsonTemplate = readProperty(loggerProperties,
  541.                 Costanti.PROP_ENABLE_JSON_TEMPLATE,
  542.                 applicationEnv,
  543.                 "classpath:JsonLayout.json");
  544.         if (jsonTemplate != null) {
  545.             for (String appenderId : appenderIds) {
  546.                 loggerProperties.remove(appenderId + LAYOUT_TYPE_SUFFIX);
  547.                 loggerProperties.remove(appenderId + LAYOUT_PATTERN_SUFFIX);
  548.                 loggerProperties.put(appenderId + LAYOUT_TYPE_SUFFIX, "JsonTemplateLayout");
  549.                 loggerProperties.put(appenderId + LAYOUT_EVENT_TEMPLATE_URI_SUFFIX, jsonTemplate.trim());
  550.             }
  551.         }
  552.        
  553.         return applyPatchLoggersJSON(loggerProperties, vars);
  554.     }
  555.     private static Properties applyPatchLoggersJSON(Properties loggerProperties, Map<String, String> vars) {
  556.        
  557.         Set<String> patchedAppenderIds = new HashSet<>();
  558.         for (Map.Entry<Object, Object> p : loggerProperties.entrySet()) {
  559.             String key = p.getKey().toString().trim();
  560.             addPatchLoggersJSONAppender(key, patchedAppenderIds, p, loggerProperties, vars);
  561.         }
  562.        
  563.         return loggerProperties;
  564.     }
  565.     private static void addPatchLoggersJSONAppender(String key, Set<String> patchedAppenderIds, Map.Entry<Object, Object> p, Properties loggerProperties, Map<String, String> vars) {
  566.         if (key.startsWith("appender")
  567.                 && key.endsWith(LAYOUT_TYPE_SUFFIX)) {
  568.             String value = p.getValue().toString().trim();
  569.             if (!value.equals("JsonTemplateLayout"))
  570.                 return;
  571.            
  572.             String appenderId = key.substring(0, key.length() - LAYOUT_TYPE_SUFFIX.length());
  573.             if (patchedAppenderIds.contains(appenderId))
  574.                 return;
  575.                
  576.             int counter = 0;
  577.             final String TEMPLATE_ADDITIONAL_FIELD = "%s.layout.eventTemplateAdditionalField[%d]";
  578.             while(counter < 1000 && loggerProperties.contains(String.format(TEMPLATE_ADDITIONAL_FIELD, appenderId, counter) + ".key")) {
  579.                 counter++;
  580.             }
  581.             for (Map.Entry<String, String> variable : vars.entrySet()) {
  582.                 loggerProperties.put(String.format(TEMPLATE_ADDITIONAL_FIELD, appenderId, counter) + ".type", "EventTemplateAdditionalField");
  583.                 loggerProperties.put(String.format(TEMPLATE_ADDITIONAL_FIELD, appenderId, counter) + ".key", variable.getKey());
  584.                 loggerProperties.put(String.format(TEMPLATE_ADDITIONAL_FIELD, appenderId, counter) + ".value", variable.getValue());
  585.             }
  586.                
  587.             patchedAppenderIds.add(appenderId);
  588.         }
  589.     }
  590.    
  591.    
  592.     private static String clusterIdEnv;
  593.     private static String clusterIdStrategy;
  594.     private static Set<String> clusterId;
  595.    

  596.     /**
  597.      * Modifica il percorso di un file aggiungendo un identificativo univoco del
  598.      * nodo
  599.      * @param filePath percorso originario del file
  600.      * @param id id della risorsa da modificare
  601.      * @return
  602.      */
  603.     public static String applyClusterIdStrategy(String filePath, String id) {
  604.         if (clusterId!=null &&
  605.                 (clusterId.contains(id) || clusterId.contains(Boolean.TRUE.toString()))
  606.                 ) {
  607.             return applyClusterIdStrategy(filePath);
  608.         }
  609.         return filePath;
  610.     }
  611.    
  612.     private static String applyClusterIdStrategy(String filePath) {
  613.         if(filePath==null) {
  614.             return null;
  615.         }
  616.         Path oldPath = Path.of(filePath);
  617.         if(oldPath==null || oldPath.getFileName()==null) {
  618.             return null;
  619.         }
  620.         String fileName = oldPath.getFileName().toString();
  621.         Path dir = oldPath.getParent();
  622.         if(dir==null) {
  623.             return null;
  624.         }
  625.        
  626.         if (clusterIdStrategy.equals(Costanti.LOG_CLUSTERID_STRATEGY_FILENAME)) {
  627.             int index = fileName.lastIndexOf('.');
  628.             index = index == -1 ? fileName.length() : index;
  629.             String name = fileName.substring(0, index);
  630.             String extension = fileName.substring(index);
  631.             fileName = name + "." + clusterIdEnv + extension;
  632.         } else if (clusterIdStrategy.equals(Costanti.LOG_CLUSTERID_STRATEGY_DIRECTORY)) {
  633.             dir = dir.resolve(clusterIdEnv);
  634.         }
  635.        
  636.         return (dir.resolve(fileName).toString());
  637.     }
  638.    
  639.     /**
  640.      * Inserisce le informazioni relative al cluster Id nel path del file di log,
  641.      * usato per condividere lo stesso file system da nodi diversi mantenendo log separati
  642.      * @param loggerProperties proprieta dei logger
  643.      * @param applicationEnv mappa contenente le variabile d'ambiente delle applicazioni
  644.      * @return
  645.      */
  646.     private static Properties patchClusterIdPath(Properties loggerProperties, Map<String, String> applicationEnv) {
  647.         clusterIdEnv = readProperty(loggerProperties,
  648.                 Costanti.PROP_ENABLE_LOG_CLUSTERID_ENV,
  649.                 applicationEnv, null);
  650.         if(clusterIdEnv!=null && StringUtils.isNotEmpty(clusterIdEnv)) {
  651.             String id = clusterIdEnv;
  652.             clusterIdEnv = System.getenv(id);
  653.             if(clusterIdEnv==null || StringUtils.isEmpty(clusterIdEnv)) {
  654.                 clusterIdEnv = System.getProperty(id);
  655.             }
  656.         }
  657.         if(clusterIdEnv==null || StringUtils.isEmpty(clusterIdEnv)) {
  658.             clusterIdEnv = System.getenv("HOSTNAME");
  659.         }
  660.         if(clusterIdEnv==null || StringUtils.isEmpty(clusterIdEnv)) {
  661.             clusterIdEnv = System.getProperty("HOSTNAME");
  662.         }
  663.         if (clusterIdEnv == null || StringUtils.isEmpty(clusterIdEnv)) {
  664.             return loggerProperties;
  665.         }
  666.         clusterId = List.of(readProperty(loggerProperties,
  667.                 Costanti.PROP_ENABLE_LOG_CLUSTERID,
  668.                 applicationEnv,
  669.                 Boolean.FALSE.toString()).split(","))
  670.                 .stream()
  671.                 .map(String::trim)
  672.                 .collect(Collectors.toSet());

  673.         Set<String> appenderIds = LoggerWrapperFactory.getAppenderIdByLoggerName(loggerProperties,
  674.                 Costanti.PROP_ENABLE_LOG_CLUSTERID,
  675.                 applicationEnv);
  676.        
  677.         if (appenderIds.isEmpty())
  678.             return loggerProperties;
  679.        
  680.         return applyPatchClusterIdPath(loggerProperties, applicationEnv, appenderIds);
  681.     }
  682.     private static Properties applyPatchClusterIdPath(Properties loggerProperties, Map<String, String> applicationEnv, Set<String> appenderIds) {  
  683.    
  684.         clusterIdStrategy = readProperty(loggerProperties,
  685.                 Costanti.PROP_ENABLE_LOG_CLUSTERID_STRATEGY,
  686.                 applicationEnv,
  687.                 Costanti.LOG_CLUSTERID_STRATEGY_DIRECTORY);
  688.         clusterIdStrategy = clusterIdStrategy.trim();
  689.        
  690.         for (Map.Entry<Object, Object> p : loggerProperties.entrySet()) {
  691.             String key = p.getKey().toString().trim();
  692.             String appenderId = null;
  693.            
  694.             if (key.startsWith(LOGGER_APPENDER_PREFIX)) {
  695.                 if (key.endsWith(".fileName"))
  696.                     appenderId = key.substring(0, key.length() - ".fileName".length());
  697.                 if (key.endsWith(".filePattern"))
  698.                     appenderId = key.substring(0, key.length() - ".filePattern".length());
  699.             }
  700.            
  701.             if (appenderId != null && appenderIds.contains(appenderId)) {
  702.                     String value = p.getValue().toString().trim();
  703.                     p.setValue(applyClusterIdStrategy(value));
  704.             }
  705.            
  706.         }
  707.        
  708.        
  709.         return loggerProperties;
  710.     }
  711.    
  712.     /**
  713.      * Aggiorna i logger per usufruire di tutti i servizi pilotati tramite variabili d'ambiente
  714.      * o proprieta nei vari file log4j2.properties, le varie proprieta sono presenti nella classe
  715.      * org.openspcoop2.utils.Costanti
  716.      * @param loggerProperties
  717.      * @param propertyToEnv
  718.      * @param vars
  719.      * @return
  720.      */
  721.     public static Properties patchLoggers(Properties loggerProperties, Map<String, String> propertyToEnv, Map<String, String> vars) {
  722.         patchClusterIdPath(loggerProperties, propertyToEnv);
  723.         patchLoggersStdout(loggerProperties, propertyToEnv, vars);
  724.         patchLoggersJSON(loggerProperties, propertyToEnv, vars);
  725.         return loggerProperties;
  726.     }


  727. }