FileTraceManager.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.pdd.logger.filetrace;

  21. import java.util.ArrayList;
  22. import java.util.HashMap;
  23. import java.util.List;
  24. import java.util.Map;

  25. import org.apache.commons.lang.StringUtils;
  26. import org.openspcoop2.core.constants.Costanti;
  27. import org.openspcoop2.core.constants.TipoPdD;
  28. import org.openspcoop2.core.transazioni.Transazione;
  29. import org.openspcoop2.core.transazioni.constants.TipoMessaggio;
  30. import org.openspcoop2.core.transazioni.utils.CredenzialiMittente;
  31. import org.openspcoop2.monitor.sdk.transaction.FaseTracciamento;
  32. import org.openspcoop2.pdd.core.token.InformazioniNegoziazioneToken;
  33. import org.openspcoop2.pdd.core.token.InformazioniToken;
  34. import org.openspcoop2.pdd.core.token.attribute_authority.InformazioniAttributi;
  35. import org.openspcoop2.pdd.core.transazioni.Transaction;
  36. import org.openspcoop2.protocol.sdk.Busta;
  37. import org.openspcoop2.protocol.sdk.Context;
  38. import org.openspcoop2.protocol.sdk.IProtocolFactory;
  39. import org.openspcoop2.protocol.sdk.ProtocolException;
  40. import org.openspcoop2.protocol.sdk.SecurityToken;
  41. import org.openspcoop2.protocol.sdk.dump.Messaggio;
  42. import org.openspcoop2.protocol.sdk.state.RequestInfo;
  43. import org.openspcoop2.utils.DynamicStringReplace;
  44. import org.openspcoop2.utils.UtilsException;
  45. import org.slf4j.Logger;

  46. /**    
  47.  * TransazioneLogTraceManager
  48.  *
  49.  * @author Poli Andrea (poli@link.it)
  50.  * @author $Author$
  51.  * @version $Rev$, $Date$
  52.  */
  53. public class FileTraceManager {
  54.    
  55.     private Logger log;
  56.     private FileTraceConfig config;
  57.    
  58.     private Map<String, Object> dynamicMap = new HashMap<>();
  59.     private Info t;
  60.     private Info tBase64;
  61.    

  62.     public FileTraceManager(Logger log, FileTraceConfig config) {
  63.         this.config = config;
  64.         this.log = log;
  65.     }
  66.    
  67.     public void buildTransazioneInfo(IProtocolFactory<?> protocolFactory, Transazione transazioneDTO, Transaction transaction,
  68.             InformazioniToken informazioniToken,
  69.             InformazioniAttributi informazioniAttributi,
  70.             InformazioniNegoziazioneToken informazioniNegoziazioneToken,
  71.             SecurityToken securityToken,
  72.             Context context,
  73.             Map<String, List<String>> headerInUscita,
  74.             FaseTracciamento trackingPhase) throws ProtocolException {
  75.        
  76.         Messaggio richiestaIngresso = null;
  77.         Messaggio richiestaUscita = null;
  78.         Messaggio rispostaIngresso = null;
  79.         Messaggio rispostaUscita = null;
  80.        
  81.         for(int i=0; i<transaction.sizeMessaggi(); i++){
  82.             Messaggio messaggio = transaction.getMessaggio(i);
  83.             TipoMessaggio tipoMessaggio = messaggio.getTipoMessaggio();
  84.             switch (tipoMessaggio) {
  85.             case RICHIESTA_INGRESSO_DUMP_BINARIO:
  86.                 richiestaIngresso = messaggio;
  87.                 break;
  88.             case RICHIESTA_USCITA_DUMP_BINARIO:
  89.                 richiestaUscita = messaggio;
  90.                 break;
  91.             case RISPOSTA_INGRESSO_DUMP_BINARIO:
  92.                 rispostaIngresso = messaggio;
  93.                 break;
  94.             case RISPOSTA_USCITA_DUMP_BINARIO:
  95.                 rispostaUscita = messaggio;
  96.                 break;
  97.             default:
  98.                 break;
  99.             }
  100.            
  101.         }
  102.        
  103.         Map<String, List<String>> headerRichiestaUscita = null;
  104.         Map<String, List<String>> headerRispostaUscita = null;
  105.         if(FaseTracciamento.OUT_REQUEST.equals(trackingPhase)) {
  106.             headerRichiestaUscita = headerInUscita;
  107.         }
  108.         else if(FaseTracciamento.OUT_RESPONSE.equals(trackingPhase)) {
  109.             headerRispostaUscita = headerInUscita;
  110.         }
  111.        
  112.         CredenzialiMittente credenzialiMittente = transaction.getCredenzialiMittente();
  113.        
  114.         InfoConfigurazione infoConfigurazione = new InfoConfigurazione(transazioneDTO, context, credenzialiMittente);
  115.        
  116.         boolean base64 = true;
  117.        
  118.         this.t = new Info(this.log, protocolFactory, transazioneDTO, credenzialiMittente,
  119.                 informazioniToken,
  120.                 informazioniAttributi,
  121.                 informazioniNegoziazioneToken,
  122.                 securityToken,
  123.                 transaction.getTracciaRichiesta(), transaction.getTracciaRisposta(),
  124.                 transaction.getMsgDiagnostici(),
  125.                 richiestaIngresso,
  126.                 richiestaUscita, headerRichiestaUscita,
  127.                 rispostaIngresso,
  128.                 rispostaUscita, headerRispostaUscita,
  129.                 infoConfigurazione,
  130.                 this.config, trackingPhase,
  131.                 !base64);
  132.         this.tBase64 = new Info(this.log, protocolFactory, transazioneDTO, credenzialiMittente,
  133.                 informazioniToken,
  134.                 informazioniAttributi,
  135.                 informazioniNegoziazioneToken,
  136.                 securityToken,
  137.                 transaction.getTracciaRichiesta(), transaction.getTracciaRisposta(),
  138.                 transaction.getMsgDiagnostici(),
  139.                 richiestaIngresso,
  140.                 richiestaUscita, headerRichiestaUscita,
  141.                 rispostaIngresso,
  142.                 rispostaUscita, headerRispostaUscita,
  143.                 infoConfigurazione,
  144.                 this.config, trackingPhase,  
  145.                 base64);
  146.        
  147.         this.dynamicMap.put("log", this.t);
  148.         this.dynamicMap.put("logBase64", this.tBase64);
  149.        
  150.     }
  151.        
  152.     public void cleanResourcesForOnlyFileTrace(Transaction transaction) throws ProtocolException {
  153.            
  154.         List<TipoMessaggio> tipiDaEliminareHeaders = transaction.getMessaggiHeadersOnlyLogFileTrace();
  155.         List<TipoMessaggio> tipiDaEliminareBody = transaction.getMessaggiBodyOnlyLogFileTrace();
  156.            
  157.         List<TipoMessaggio> messaggiDaEliminare = new ArrayList<>();
  158.        
  159.         for(int i=0; i<transaction.sizeMessaggi(); i++){
  160.             Messaggio messaggio = transaction.getMessaggio(i);
  161.             TipoMessaggio tipoMessaggio = messaggio.getTipoMessaggio();
  162.            
  163.             boolean onlyLogFileTraceHeaders = false;
  164.             if(tipiDaEliminareHeaders!=null && !tipiDaEliminareHeaders.isEmpty()) {
  165.                 for (int j = 0; j < tipiDaEliminareHeaders.size(); j++) {
  166.                     TipoMessaggio tipoMessaggioHeaders = tipiDaEliminareHeaders.get(j);
  167.                     if(tipoMessaggioHeaders.equals(tipoMessaggio)) {
  168.                         onlyLogFileTraceHeaders = true;
  169.                         break;
  170.                     }
  171.                 }
  172.             }
  173.             if(onlyLogFileTraceHeaders) {
  174.                 tipiDaEliminareHeaders.remove(tipoMessaggio);  
  175.             }
  176.            
  177.             boolean onlyLogFileTraceBody = false;
  178.             if(tipiDaEliminareBody!=null && !tipiDaEliminareBody.isEmpty()) {
  179.                 for (int j = 0; j < tipiDaEliminareBody.size(); j++) {
  180.                     TipoMessaggio tipoMessaggioBody = tipiDaEliminareBody.get(j);
  181.                     if(tipoMessaggioBody.equals(tipoMessaggio)) {
  182.                         onlyLogFileTraceBody = true;
  183.                         break;
  184.                     }
  185.                 }
  186.             }
  187.             if(onlyLogFileTraceBody) {
  188.                 tipiDaEliminareBody.remove(tipoMessaggio);  
  189.             }
  190.            
  191.             if(onlyLogFileTraceHeaders && onlyLogFileTraceBody) {
  192.                 messaggiDaEliminare.add(tipoMessaggio);
  193.             }
  194.             else if(onlyLogFileTraceHeaders) {
  195.                 messaggio.getHeaders().clear();
  196.             }
  197.             else if(onlyLogFileTraceBody) {
  198.                 if(messaggio.getBody()!=null) {
  199.                     messaggio.getBody().unlock();
  200.                     messaggio.getBody().clearResources();
  201.                     messaggio.setBody(null);
  202.                 }
  203.                 messaggio.setContentType(null);
  204.             }
  205.         }
  206.        
  207.         if(messaggiDaEliminare!=null) {
  208.             while(!messaggiDaEliminare.isEmpty()) {
  209.                 TipoMessaggio tipo = messaggiDaEliminare.remove(0);
  210.                 if(transaction.sizeMessaggi()>0) {
  211.                     for (int i = 0; i < transaction.sizeMessaggi(); i++) {
  212.                         if(tipo.equals(transaction.getMessaggio(i).getTipoMessaggio())) {
  213.                             if(transaction.getMessaggio(i).getBody()!=null){
  214.                                 transaction.getMessaggio(i).getBody().unlock();
  215.                                 transaction.getMessaggio(i).getBody().clearResources();
  216.                                 transaction.getMessaggio(i).setBody(null);
  217.                             }
  218.                             transaction.removeMessaggio(i);
  219.                             break;
  220.                         }
  221.                     }
  222.                 }
  223.             }
  224.         }

  225.     }
  226.    
  227.     public void invoke(TipoPdD tipoPdD, Context context, RequestInfo requestInfo, Busta busta, FaseTracciamento faseTracciamento) throws UtilsException {
  228.         this.invoke(tipoPdD, context, requestInfo, busta, faseTracciamento, null);
  229.     }
  230.     public void invoke(TipoPdD tipoPdD, Context context, RequestInfo requestInfo, Busta busta, FaseTracciamento faseTracciamento, Map<String, String> outputMap) throws UtilsException {
  231.         List<String> topic = null;
  232.         Map<String, Topic> topicMap = null;
  233.         switch (tipoPdD) {
  234.         case DELEGATA:
  235.             topic = this.config.getTopicFruizioni();
  236.             topicMap = this.config.getTopicFruizioneMap();
  237.             break;
  238.         case APPLICATIVA:
  239.             topic = this.config.getTopicErogazioni();
  240.             topicMap = this.config.getTopicErogazioniMap();
  241.             break;
  242.         default:
  243.             break;
  244.         }
  245.         if(topic!=null && !topic.isEmpty()) {
  246.            
  247.             boolean requestSent = isRequestSent(context);
  248.            
  249.             List<Topic> topicInvoke = new ArrayList<>();
  250.             for (String topicName : topic) {
  251.                 Topic topicConfig = topicMap.get(topicName);
  252.                 if(add(topicConfig, faseTracciamento, requestSent)) {
  253.                     topicInvoke.add(topicConfig);
  254.                 }
  255.                 /**else {
  256.                     System.out.println("SKIP["+topicName+"] in fase ["+faseTracciamento+"]");
  257.                 }*/
  258.             }
  259.            
  260.             invoke(topicInvoke,
  261.                     requestInfo, context, busta,
  262.                     outputMap);
  263.         }
  264.     }
  265.    
  266.     private boolean isRequestSent(Context context) {
  267.         boolean requestSent = false;
  268.         if(context!=null && context.containsKey(Costanti.RICHIESTA_INOLTRATA_BACKEND)) {
  269.             Object o = context.getObject(Costanti.RICHIESTA_INOLTRATA_BACKEND);
  270.             if(o instanceof String) {
  271.                 String s = (String) o;
  272.                 if(Costanti.RICHIESTA_INOLTRATA_BACKEND_VALORE.equals(s)) {
  273.                     requestSent = true;
  274.                 }
  275.             }
  276.         }
  277.         return requestSent;
  278.     }
  279.    
  280.     private boolean add(Topic topicConfig, FaseTracciamento faseTracciamento, boolean requestSent) {
  281.         if(!topicConfig.isEnabled(faseTracciamento)) {
  282.             /**System.out.println("R1");*/
  283.             return false;
  284.         }
  285.        
  286.         if(topicConfig.isOnlyRequestSent() &&
  287.             !requestSent) {
  288.             /**System.out.println("R1");*/
  289.             return false;
  290.         }
  291.         if(topicConfig.isOnlyInRequestContentDefined()) {
  292.             boolean contentDefined = this.t.getInRequestSize()>0;
  293.             if(!contentDefined) {
  294.                 /**System.out.println("R3");*/
  295.                 return false;
  296.             }
  297.         }
  298.         if(topicConfig.isOnlyOutRequestContentDefined()) {
  299.             boolean contentDefined = this.t.getOutRequestSize()>0;
  300.             if(!contentDefined) {
  301.                 /**System.out.println("R4");*/
  302.                 return false;
  303.             }
  304.         }
  305.         if(topicConfig.isOnlyInResponseContentDefined()) {
  306.             boolean contentDefined = this.t.getInResponseSize()>0;
  307.             if(!contentDefined) {
  308.                 /**System.out.println("R5");*/
  309.                 return false;
  310.             }
  311.         }
  312.         if(topicConfig.isOnlyOutResponseContentDefined()) {
  313.             boolean contentDefined = this.t.getOutResponseSize()>0;
  314.             if(!contentDefined) {
  315.                 /**System.out.println("R6");*/
  316.                 return false;
  317.             }
  318.         }
  319.        
  320.         return true;
  321.     }
  322.    
  323.     private void invoke(List<Topic> topicInvoke,
  324.             RequestInfo requestInfo, Context context, Busta busta,
  325.             Map<String, String> outputMap) throws UtilsException {
  326.         if(topicInvoke!=null && !topicInvoke.isEmpty()) {
  327.            
  328.             this.resolveProperties(requestInfo, context, busta);
  329.            
  330.             for (Topic topicConfig : topicInvoke) {
  331.                 String value = this.resolve(topicConfig.getFormat());
  332.                 if(outputMap!=null) {
  333.                     outputMap.put(topicConfig.getNome(), value);
  334.                 }
  335.                 else {
  336.                     switch (this.config.getLogSeverity()) {
  337.                     case trace:
  338.                         topicConfig.getLog().trace(value);      
  339.                         break;
  340.                     case debug:
  341.                         topicConfig.getLog().debug(value);      
  342.                         break;
  343.                     case info:
  344.                         topicConfig.getLog().info(value);      
  345.                         break;
  346.                     case warn:
  347.                         topicConfig.getLog().warn(value);      
  348.                         break;
  349.                     case error:
  350.                         topicConfig.getLog().error(value);      
  351.                         break;
  352.                     }
  353.                 }
  354.             }
  355.         }
  356.     }
  357.        
  358.     private void resolveProperties(RequestInfo requestInfo, Context context, Busta busta) throws UtilsException {
  359.        
  360.         Map<String, String> propertiesEncryptionModes = this.config.getPropertiesEncryptionMode();
  361.         FileTraceEncrypt encrypt = null;
  362.         if(!propertiesEncryptionModes.isEmpty()) {
  363.             encrypt = new FileTraceEncrypt(this.log, requestInfo, context, busta);
  364.         }
  365.        
  366.         List<String> properties = this.config.getPropertiesSortKeys();
  367.         if(properties!=null && !properties.isEmpty()) {
  368.             for (String sortKey : properties) {
  369.                 String pName = this.config.getPropertiesNames().get(sortKey);
  370.                 String pValue = this.config.getPropertiesValues().get(sortKey);
  371.                 /**System.out.println("SORT ["+sortKey+"] ["+pName+"]");*/
  372.                 String resolvedValue = this.resolve(pValue);
  373.                
  374.                 String mode = propertiesEncryptionModes.get(sortKey);
  375.                 if(encrypt!=null && mode!=null && StringUtils.isNotEmpty(mode)) {
  376.                     FileTraceEncryptConfig encryptionConfig = this.config.getEncryptionMode().get(mode);
  377.                     resolvedValue = encrypt.encrypt(encryptionConfig, resolvedValue);
  378.                 }
  379.                
  380.                 this.t.addProperty(pName, resolvedValue);
  381.                 this.tBase64.addProperty(pName, resolvedValue);
  382.             }
  383.         }
  384.     }
  385.    
  386.     private String resolve(String format) throws UtilsException {
  387.         boolean complexField = false;
  388.         return DynamicStringReplace.replace(format, this.dynamicMap, true, complexField);
  389.     }
  390. }