DumpProducer.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.protocol.basic.dump;

  21. import java.io.File;
  22. import java.io.FileInputStream;
  23. import java.sql.Connection;
  24. import java.sql.PreparedStatement;
  25. import java.text.SimpleDateFormat;
  26. import java.util.ArrayList;
  27. import java.util.Date;
  28. import java.util.HashMap;
  29. import java.util.Iterator;
  30. import java.util.List;
  31. import java.util.Map;

  32. import org.openspcoop2.core.config.OpenspcoopAppender;
  33. import org.openspcoop2.core.constants.CostantiDB;
  34. import org.openspcoop2.core.transazioni.DumpAllegato;
  35. import org.openspcoop2.core.transazioni.DumpContenuto;
  36. import org.openspcoop2.core.transazioni.DumpHeaderAllegato;
  37. import org.openspcoop2.core.transazioni.DumpHeaderTrasporto;
  38. import org.openspcoop2.core.transazioni.DumpMessaggio;
  39. import org.openspcoop2.core.transazioni.DumpMultipartHeader;
  40. import org.openspcoop2.core.transazioni.constants.TipoMessaggio;
  41. import org.openspcoop2.core.transazioni.dao.jdbc.JDBCServiceManager;
  42. import org.openspcoop2.core.transazioni.utils.PropertiesSerializator;
  43. import org.openspcoop2.core.transazioni.utils.TransactionContentUtils;
  44. import org.openspcoop2.generic_project.utils.ServiceManagerProperties;
  45. import org.openspcoop2.message.constants.MessageType;
  46. import org.openspcoop2.protocol.basic.BasicConnectionResult;
  47. import org.openspcoop2.protocol.basic.BasicProducer;
  48. import org.openspcoop2.protocol.basic.BasicProducerType;
  49. import org.openspcoop2.protocol.sdk.IProtocolFactory;
  50. import org.openspcoop2.protocol.sdk.ProtocolException;
  51. import org.openspcoop2.protocol.sdk.dump.Attachment;
  52. import org.openspcoop2.protocol.sdk.dump.DumpException;
  53. import org.openspcoop2.protocol.sdk.dump.IDumpProducer;
  54. import org.openspcoop2.protocol.sdk.dump.Messaggio;
  55. import org.openspcoop2.protocol.sdk.tracciamento.TracciamentoException;
  56. import org.openspcoop2.utils.Utilities;
  57. import org.openspcoop2.utils.date.DateUtils;
  58. import org.openspcoop2.utils.jdbc.IJDBCAdapter;
  59. import org.openspcoop2.utils.jdbc.JDBCAdapterFactory;
  60. import org.openspcoop2.utils.sql.ISQLQueryObject;
  61. import org.openspcoop2.utils.sql.SQLObjectFactory;
  62. import org.openspcoop2.utils.transport.TransportUtils;




  63. /**
  64.  * Contiene l'implementazione di un appender personalizzato,
  65.  * per la registrazione del dump su database.
  66.  *
  67.  * @author Poli Andrea (apoli@link.it)
  68.  * @author $Author$
  69.  * @version $Rev$, $Date$
  70.  */

  71. public class DumpProducer extends BasicProducer implements IDumpProducer{

  72.     public DumpProducer(IProtocolFactory<?> factory) throws ProtocolException{
  73.         super(factory, BasicProducerType.DUMP);
  74.     }

  75.     /**
  76.      * Inizializza l'engine di un appender per la registrazione
  77.      * di un tracciamento emesso da una porta di dominio.
  78.      *
  79.      * @param appenderProperties Proprieta' dell'appender
  80.      * @throws TracciamentoException
  81.      */
  82.     @Override
  83.     public void initializeAppender(OpenspcoopAppender appenderProperties) throws DumpException{
  84.         try{
  85.             this.initializeAppender(appenderProperties, true);
  86.         }catch(Exception e){
  87.             throw new DumpException("Errore durante l'inizializzazione dell'appender: "+e.getMessage(),e);
  88.         }
  89.     }



  90.     /**
  91.      * Dump di un messaggio
  92.      *
  93.      * @param conOpenSPCoopPdD Connessione verso il database
  94.      * @param messaggio
  95.      * @throws DumpException
  96.      */
  97.     @SuppressWarnings("deprecation")
  98.     @Deprecated
  99.     @Override
  100.     public void dump(Connection conOpenSPCoopPdD,Messaggio messaggio) throws DumpException{
  101.         this.dump(conOpenSPCoopPdD, messaggio, false);
  102.     }
  103.     @Override
  104.     public void dump(Connection conOpenSPCoopPdD,Messaggio messaggio,boolean headersCompact) throws DumpException{

  105.         if(messaggio==null)
  106.             throw new DumpException("Errore durante il dump: messaggio is null");

  107.         if(messaggio.getIdTransazione()==null)
  108.             throw new DumpException("Errore durante il dump: id transazione is null");

  109.         Date gdo = messaggio.getGdo();
  110.        
  111.         String protocollo = messaggio.getProtocollo();
  112.        
  113.         String idTransazione = messaggio.getIdTransazione();
  114.        
  115.         TipoMessaggio tipoMessaggio = messaggio.getTipoMessaggio();
  116.        
  117.         MessageType formatoMessaggio = messaggio.getFormatoMessaggio();
  118.        
  119.         String servizioApplicativoErogatore = messaggio.getServizioApplicativoErogatore();
  120.         Date dataConsegnaErogatore = messaggio.getDataConsegna();
  121.        
  122.         String identificativoDump = "["+idTransazione+"]["+tipoMessaggio+"]";
  123.         if(servizioApplicativoErogatore!=null) {
  124.             identificativoDump=identificativoDump+"["+servizioApplicativoErogatore+"]";
  125.         }
  126.         if(dataConsegnaErogatore!=null) {
  127.             identificativoDump=identificativoDump+"["+DateUtils.getSimpleDateFormatMs().format(dataConsegnaErogatore)+"]";
  128.         }
  129.        
  130.         if(this.debug){
  131.             this.log.debug("@@ log"+identificativoDump+" ....");
  132.         }
  133.        
  134.         Connection con = null;
  135.         BasicConnectionResult cr = null;
  136.         try{
  137.             //  Connessione al DB
  138.             cr = this.getConnection(conOpenSPCoopPdD,"dump.log");
  139.             con = cr.getConnection();

  140.             if(this.debug){
  141.                 this.log.debug("@@ log"+identificativoDump+" (getConnection finished) ....");
  142.             }
  143.            
  144.             ServiceManagerProperties smProperties = new ServiceManagerProperties();
  145.             smProperties.setDatabaseType(this.tipoDatabase);
  146.             smProperties.setShowSql(this.debug);
  147.             smProperties.setAutomaticTransactionManagement(con.getAutoCommit());
  148.             JDBCServiceManager jdbcServiceManager = new JDBCServiceManager(con, smProperties);
  149.            
  150.             org.openspcoop2.core.transazioni.dao.IDumpMessaggioService dumpMessageService = jdbcServiceManager.getDumpMessaggioService();
  151.            
  152.             SimpleDateFormat dateformat = null;
  153.             if(this.debug) {
  154.                 dateformat = DateUtils.getSimpleDateFormatMs();
  155.             }
  156.                        
  157.             // MESSAGGIO BASE
  158.            
  159.             File fDump = null;
  160.            
  161.             DumpMessaggio dumpMessaggio = new DumpMessaggio();
  162.             dumpMessaggio.setProtocollo(protocollo);
  163.             dumpMessaggio.setIdTransazione(idTransazione);
  164.             dumpMessaggio.setServizioApplicativoErogatore(servizioApplicativoErogatore);
  165.             dumpMessaggio.setDataConsegnaErogatore(dataConsegnaErogatore);
  166.             dumpMessaggio.setTipoMessaggio(tipoMessaggio);
  167.                        
  168.             if(this.debug){
  169.                 this.log.debug("formato-messaggio: "+formatoMessaggio);
  170.                 this.log.debug("gdo: "+dateformat.format(gdo));
  171.                 this.log.debug("content-type["+messaggio.getContentType()+"]");
  172.                 if(messaggio.getBody()==null) {
  173.                     this.log.debug("body undefined");
  174.                 }
  175.                 else {
  176.                     this.log.debug("body: "+Utilities.convertBytesToFormatString(messaggio.getBody().size()));
  177.                 }
  178.             }
  179.             if(formatoMessaggio!=null) {
  180.                 dumpMessaggio.setFormatoMessaggio(formatoMessaggio.name());
  181.             }
  182.             dumpMessaggio.setDumpTimestamp(gdo);
  183.             dumpMessaggio.setContentType(messaggio.getContentType());
  184.             if(messaggio.getBody()!=null && messaggio.getBody().size()>0) {
  185.                 if(!messaggio.getBody().isSerializedOnFileSystem()) {          
  186.                     dumpMessaggio.setBody(messaggio.getBody().toByteArray());
  187.                     dumpMessaggio.setContentLength(Long.valueOf(messaggio.getBody().size()));
  188.                 }
  189.                 else {
  190.                     fDump = messaggio.getBody().getSerializedFile();
  191.                     dumpMessaggio.setContentLength(fDump.length());
  192.                 }
  193.             }
  194.            
  195.             if(messaggio.getBodyMultipartInfo()!=null) {
  196.                 if(this.debug){
  197.                     this.log.debug("multipart-body-content-id["+messaggio.getBodyMultipartInfo().getContentId()+"]");
  198.                     this.log.debug("multipart-body-content-location["+messaggio.getBodyMultipartInfo().getContentLocation()+"]");
  199.                     this.log.debug("multipart-body-content-type["+messaggio.getBodyMultipartInfo().getContentType()+"]");
  200.                 }
  201.                 dumpMessaggio.setMultipartContentId(messaggio.getBodyMultipartInfo().getContentId());
  202.                 dumpMessaggio.setMultipartContentLocation(messaggio.getBodyMultipartInfo().getContentLocation());
  203.                 dumpMessaggio.setMultipartContentType(messaggio.getBodyMultipartInfo().getContentType());
  204.                 if(messaggio.getBodyMultipartInfo().getHeaders()!=null &&
  205.                         messaggio.getBodyMultipartInfo().getHeaders().size()>0) {
  206.                     if(this.debug){
  207.                         this.log.debug("Dump "+messaggio.getBodyMultipartInfo().getHeaders().size()+" multipart-body headers");
  208.                     }
  209.                    
  210.                     Map<String, List<String>> propertiesHdr = new HashMap<>();
  211.                     List<DumpMultipartHeader> backupFailed = new ArrayList<DumpMultipartHeader>();
  212.                    
  213.                     Iterator<String> keys = messaggio.getBodyMultipartInfo().getHeaders().keySet().iterator();
  214.                     while (keys.hasNext()) {
  215.                         String key = (String) keys.next();
  216.                        
  217.                         List<String> values = messaggio.getBodyMultipartInfo().getHeaders().get(key);
  218.                         if(values!=null && !values.isEmpty()) {
  219.                             for (String value : values) {
  220.                                 if(value==null){
  221.                                     value = ""; // puo' succedere in alcuni casi.
  222.                                 }
  223.                                 if(this.debug){
  224.                                     this.log.debug("\t\t"+key+"="+value);
  225.                                 }
  226.                                
  227.                                 DumpMultipartHeader headerMultipart = new DumpMultipartHeader();
  228.                                 headerMultipart.setNome(key);
  229.                                 headerMultipart.setValore(value.toString());
  230.                                 headerMultipart.setDumpTimestamp(gdo);
  231.                                
  232.                                 if(headersCompact) {
  233.                                     TransportUtils.addHeader(propertiesHdr, key, value);
  234.                                     backupFailed.add(headerMultipart);
  235.                                 }
  236.                                 else {
  237.                                     dumpMessaggio.addMultipartHeader(headerMultipart);
  238.                                 }      
  239.                             }
  240.                         }
  241.                        
  242.                     }
  243.                    
  244.                     if(headersCompact) {
  245.                         PropertiesSerializator ps = new PropertiesSerializator(propertiesHdr);
  246.                         try{
  247.                             dumpMessaggio.setMultipartHeaderExt(ps.convertToDBColumnValue());
  248.                             backupFailed.clear();
  249.                             backupFailed = null;
  250.                         }catch(Throwable e){
  251.                             // NOTA: questo metodo dovrebbe non lanciare praticamente mai eccezione
  252.                             this.log.error("Errore durante la conversione degli header multipart: "+e.getMessage(),e);
  253.                             for (DumpMultipartHeader dumpMultipartHeader : backupFailed) {
  254.                                 dumpMessaggio.addMultipartHeader(dumpMultipartHeader);
  255.                             }
  256.                         }
  257.                     }
  258.                 }
  259.             }
  260.            
  261.             dumpMessaggio.setPostProcessed(1);
  262.            
  263.            
  264.            
  265.             // HEADER TRASPORTO
  266.             if(messaggio.getHeaders()!=null && messaggio.getHeaders().size()>0){
  267.                 if(this.debug){
  268.                     this.log.debug("Dump "+messaggio.getHeaders().size()+" headers");
  269.                 }

  270.                 Map<String, List<String>> propertiesHdr = new HashMap<>();
  271.                 List<DumpHeaderTrasporto> backupFailed = new ArrayList<DumpHeaderTrasporto>();
  272.                
  273.                 Iterator<String> keys = messaggio.getHeaders().keySet().iterator();
  274.                 while (keys.hasNext()) {
  275.                     String key = (String) keys.next();
  276.                    
  277.                     List<String> values = messaggio.getHeaders().get(key);
  278.                     if(values!=null && !values.isEmpty()) {
  279.                         for (String value : values) {              
  280.                             if(value==null){
  281.                                 value = ""; // puo' succedere in alcuni casi.
  282.                             }
  283.                             if(this.debug){
  284.                                 this.log.debug("\t\t"+key+"="+value);
  285.                             }
  286.        
  287.                             DumpHeaderTrasporto headerTrasporto = new DumpHeaderTrasporto();
  288.                             headerTrasporto.setNome(key);
  289.                             headerTrasporto.setValore(value.toString());
  290.                             headerTrasporto.setDumpTimestamp(gdo);
  291.                            
  292.                             if(headersCompact) {
  293.                                 TransportUtils.addHeader(propertiesHdr,key, value);
  294.                                 backupFailed.add(headerTrasporto);
  295.                             }
  296.                             else {
  297.                                 dumpMessaggio.addHeaderTrasporto(headerTrasporto);
  298.                             }
  299.                         }
  300.                     }
  301.                 }
  302.                
  303.                 if(headersCompact) {
  304.                     PropertiesSerializator ps = new PropertiesSerializator(propertiesHdr);
  305.                     try{
  306.                         dumpMessaggio.setHeaderExt(ps.convertToDBColumnValue());
  307.                         backupFailed.clear();
  308.                         backupFailed = null;
  309.                     }catch(Throwable e){
  310.                         // NOTA: questo metodo dovrebbe non lanciare praticamente mai eccezione
  311.                         this.log.error("Errore durante la conversione degli header: "+e.getMessage(),e);
  312.                         for (DumpHeaderTrasporto dumpHeader : backupFailed) {
  313.                             dumpMessaggio.addHeaderTrasporto(dumpHeader);
  314.                         }
  315.                     }
  316.                 }
  317.             }
  318.            
  319.             // ALLEGATI
  320.             if(messaggio.getAttachments()!=null && messaggio.getAttachments().size()>0) {
  321.                
  322.                 if(this.debug){
  323.                     this.log.debug("Dump "+messaggio.getAttachments().size()+" attachments");
  324.                 }
  325.                
  326.                 for (Attachment attach : messaggio.getAttachments()) {
  327.                     if(this.debug){
  328.                         this.log.debug("Attachment:");
  329.                         this.log.debug("\t\tId["+attach.getContentId()+"]");
  330.                         this.log.debug("\t\tlocation["+attach.getContentLocation()+"]");
  331.                         this.log.debug("\t\ttype["+attach.getContentType()+"]");
  332.                         if(attach.getContent()==null) {
  333.                             this.log.debug("\t\tcontent undefined");
  334.                         }
  335.                         else {
  336.                             this.log.debug("\t\tcontent: "+Utilities.convertBytesToFormatString(attach.getContent().length));
  337.                         }
  338.                     }

  339.                     DumpAllegato dumpAllegato = new DumpAllegato();
  340.                     dumpAllegato.setContentId(attach.getContentId());
  341.                     dumpAllegato.setContentLocation(attach.getContentLocation());
  342.                     dumpAllegato.setContentType(attach.getContentType());
  343.                     dumpAllegato.setAllegato(attach.getContent());
  344.                     dumpAllegato.setDumpTimestamp(gdo);
  345.                     dumpMessaggio.addAllegato(dumpAllegato);
  346.                    
  347.                    
  348.                     if(attach.getHeaders()!=null && attach.getHeaders().size()>0){
  349.                         if(this.debug){
  350.                             this.log.debug("Dump "+attach.getHeaders().size()+" headers dell'allegato con id ["+attach.getContentId()+"]");
  351.                         }

  352.                         Map<String, List<String>> propertiesHdr = new HashMap<>();
  353.                         List<DumpHeaderAllegato> backupFailed = new ArrayList<DumpHeaderAllegato>();
  354.                                                
  355.                         Iterator<String> keys = attach.getHeaders().keySet().iterator();
  356.                         while (keys.hasNext()) {
  357.                             String key = (String) keys.next();
  358.                            
  359.                             List<String> values = attach.getHeaders().get(key);
  360.                             if(values!=null && !values.isEmpty()) {
  361.                                 for (String value : values) {
  362.                                     if(value==null){
  363.                                         value = ""; // puo' succedere in alcuni casi.
  364.                                     }
  365.                                     if(this.debug){
  366.                                         this.log.debug("\t\t"+key+"="+value);
  367.                                     }
  368.        
  369.                                     DumpHeaderAllegato headerAllegato = new DumpHeaderAllegato();
  370.                                     headerAllegato.setNome(key);
  371.                                     headerAllegato.setValore(value.toString());
  372.                                     headerAllegato.setDumpTimestamp(gdo);
  373.                                    
  374.                                     if(headersCompact) {
  375.                                         TransportUtils.addHeader(propertiesHdr,key, value);
  376.                                         backupFailed.add(headerAllegato);
  377.                                     }
  378.                                     else {
  379.                                         dumpAllegato.addHeader(headerAllegato);
  380.                                     }
  381.                                 }
  382.                             }
  383.                         }
  384.                        
  385.                         if(headersCompact) {
  386.                             PropertiesSerializator ps = new PropertiesSerializator(propertiesHdr);
  387.                             try{
  388.                                 dumpAllegato.setHeaderExt(ps.convertToDBColumnValue());
  389.                                 backupFailed.clear();
  390.                                 backupFailed = null;
  391.                             }catch(Throwable e){
  392.                                 // NOTA: questo metodo dovrebbe non lanciare praticamente mai eccezione
  393.                                 this.log.error("Errore durante la conversione degli header dell'allegato '"+attach.getContentId()+"': "+e.getMessage(),e);
  394.                                 for (DumpHeaderAllegato dumpHeader : backupFailed) {
  395.                                     dumpAllegato.addHeader(dumpHeader);
  396.                                 }
  397.                             }
  398.                         }
  399.                     }
  400.                 }
  401.                    
  402.             }
  403.            
  404.             // CONTENUTI
  405.             if(messaggio.getContenuti()!=null && messaggio.getContenuti().size()>0){
  406.                 if(this.debug){
  407.                     this.log.debug("Dump "+messaggio.getContenuti().size()+" contenuti");
  408.                 }

  409.                 Iterator<String> keys = messaggio.getContenuti().keySet().iterator();
  410.                 while (keys.hasNext()) {
  411.                     String key = (String) keys.next();
  412.                    
  413.                     String value = messaggio.getContenuti().get(key);
  414.                     if(value==null){
  415.                         value = ""; // puo' succedere in alcuni casi.
  416.                     }

  417.                     DumpContenuto contenuto = TransactionContentUtils.createDumpContenuto(key, value, gdo);
  418.                    
  419.                     if(this.debug){
  420.                         this.log.debug("\t\t"+key+"="+value);
  421.                     }
  422.                    
  423.                     dumpMessaggio.addContenuto(contenuto);
  424.                 }
  425.             }
  426.            
  427.             if(this.debug){
  428.                 this.log.debug("@@ log"+identificativoDump+" registrazione in corso ...");
  429.             }
  430.            
  431.             dumpMessageService.create(dumpMessaggio);
  432.            
  433.             if(fDump!=null) {
  434.                
  435.                 ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.tipoDatabase);
  436.                 sqlQueryObject.addUpdateTable(CostantiDB.DUMP_MESSAGGI);
  437.                 sqlQueryObject.addUpdateField("body", "?");
  438.                 sqlQueryObject.addWhereCondition(CostantiDB.DUMP_MESSAGGI+".id=?");
  439.                
  440.                 IJDBCAdapter jdbcAdapter = JDBCAdapterFactory.createJDBCAdapter(this.tipoDatabase);
  441.                
  442.                 String sqlQueryUpdate =sqlQueryObject.createSQLUpdate();
  443.                 PreparedStatement pstmt = null;
  444.                 try {
  445.                     try(FileInputStream fin = new FileInputStream(fDump)){
  446.                         int index = 1;
  447.                         pstmt = con.prepareStatement(sqlQueryUpdate);
  448.                         jdbcAdapter.setBinaryData(pstmt, index++, fin, true);
  449.                         pstmt.setLong(index++, dumpMessaggio.getId());
  450.                         pstmt.execute();
  451.                     }
  452.                 }finally {
  453.                     try {
  454.                         if(pstmt!=null) {
  455.                             pstmt.close();
  456.                         }
  457.                     }catch(Exception eClose) {
  458.                         // close
  459.                     }
  460.                 }
  461.             }
  462.            
  463.             if(this.debug){
  464.                 this.log.debug("@@ log"+identificativoDump+" registrazione completata");
  465.             }

  466.         }catch(Exception e){
  467.             throw new DumpException("Errore durante il dump del messaggio idTransazione["+idTransazione+"] tipoMessaggio["+tipoMessaggio+"]: "+e.getMessage(),e);
  468.         }finally{
  469.             try{
  470.                 this.releaseConnection(cr, "dump.log");
  471.             }catch(Exception e){
  472.                 // close
  473.             }
  474.         }
  475.     }


  476. }