DumpProducer.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.protocol.basic.dump;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.openspcoop2.core.config.OpenspcoopAppender;
import org.openspcoop2.core.constants.CostantiDB;
import org.openspcoop2.core.transazioni.DumpAllegato;
import org.openspcoop2.core.transazioni.DumpContenuto;
import org.openspcoop2.core.transazioni.DumpHeaderAllegato;
import org.openspcoop2.core.transazioni.DumpHeaderTrasporto;
import org.openspcoop2.core.transazioni.DumpMessaggio;
import org.openspcoop2.core.transazioni.DumpMultipartHeader;
import org.openspcoop2.core.transazioni.constants.TipoMessaggio;
import org.openspcoop2.core.transazioni.dao.jdbc.JDBCServiceManager;
import org.openspcoop2.core.transazioni.utils.PropertiesSerializator;
import org.openspcoop2.core.transazioni.utils.TransactionContentUtils;
import org.openspcoop2.generic_project.utils.ServiceManagerProperties;
import org.openspcoop2.message.constants.MessageType;
import org.openspcoop2.protocol.basic.BasicConnectionResult;
import org.openspcoop2.protocol.basic.BasicProducer;
import org.openspcoop2.protocol.basic.BasicProducerType;
import org.openspcoop2.protocol.sdk.IProtocolFactory;
import org.openspcoop2.protocol.sdk.ProtocolException;
import org.openspcoop2.protocol.sdk.dump.Attachment;
import org.openspcoop2.protocol.sdk.dump.DumpException;
import org.openspcoop2.protocol.sdk.dump.IDumpProducer;
import org.openspcoop2.protocol.sdk.dump.Messaggio;
import org.openspcoop2.protocol.sdk.tracciamento.TracciamentoException;
import org.openspcoop2.utils.Utilities;
import org.openspcoop2.utils.date.DateUtils;
import org.openspcoop2.utils.jdbc.IJDBCAdapter;
import org.openspcoop2.utils.jdbc.JDBCAdapterFactory;
import org.openspcoop2.utils.sql.ISQLQueryObject;
import org.openspcoop2.utils.sql.SQLObjectFactory;
import org.openspcoop2.utils.transport.TransportUtils;
/**
* Contiene l'implementazione di un appender personalizzato,
* per la registrazione del dump su database.
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class DumpProducer extends BasicProducer implements IDumpProducer{
public DumpProducer(IProtocolFactory<?> factory) throws ProtocolException{
super(factory, BasicProducerType.DUMP);
}
/**
* Inizializza l'engine di un appender per la registrazione
* di un tracciamento emesso da una porta di dominio.
*
* @param appenderProperties Proprieta' dell'appender
* @throws TracciamentoException
*/
@Override
public void initializeAppender(OpenspcoopAppender appenderProperties) throws DumpException{
try{
this.initializeAppender(appenderProperties, true);
}catch(Exception e){
throw new DumpException("Errore durante l'inizializzazione dell'appender: "+e.getMessage(),e);
}
}
/**
* Dump di un messaggio
*
* @param conOpenSPCoopPdD Connessione verso il database
* @param messaggio
* @throws DumpException
*/
@SuppressWarnings("deprecation")
@Deprecated
@Override
public void dump(Connection conOpenSPCoopPdD,Messaggio messaggio) throws DumpException{
this.dump(conOpenSPCoopPdD, messaggio, false);
}
@Override
public void dump(Connection conOpenSPCoopPdD,Messaggio messaggio,boolean headersCompact) throws DumpException{
if(messaggio==null)
throw new DumpException("Errore durante il dump: messaggio is null");
if(messaggio.getIdTransazione()==null)
throw new DumpException("Errore durante il dump: id transazione is null");
Date gdo = messaggio.getGdo();
String protocollo = messaggio.getProtocollo();
String idTransazione = messaggio.getIdTransazione();
TipoMessaggio tipoMessaggio = messaggio.getTipoMessaggio();
MessageType formatoMessaggio = messaggio.getFormatoMessaggio();
String servizioApplicativoErogatore = messaggio.getServizioApplicativoErogatore();
Date dataConsegnaErogatore = messaggio.getDataConsegna();
String identificativoDump = "["+idTransazione+"]["+tipoMessaggio+"]";
if(servizioApplicativoErogatore!=null) {
identificativoDump=identificativoDump+"["+servizioApplicativoErogatore+"]";
}
if(dataConsegnaErogatore!=null) {
identificativoDump=identificativoDump+"["+DateUtils.getSimpleDateFormatMs().format(dataConsegnaErogatore)+"]";
}
if(this.debug){
this.log.debug("@@ log"+identificativoDump+" ....");
}
Connection con = null;
BasicConnectionResult cr = null;
try{
// Connessione al DB
cr = this.getConnection(conOpenSPCoopPdD,"dump.log");
con = cr.getConnection();
if(this.debug){
this.log.debug("@@ log"+identificativoDump+" (getConnection finished) ....");
}
ServiceManagerProperties smProperties = new ServiceManagerProperties();
smProperties.setDatabaseType(this.tipoDatabase);
smProperties.setShowSql(this.debug);
smProperties.setAutomaticTransactionManagement(con.getAutoCommit());
JDBCServiceManager jdbcServiceManager = new JDBCServiceManager(con, smProperties);
org.openspcoop2.core.transazioni.dao.IDumpMessaggioService dumpMessageService = jdbcServiceManager.getDumpMessaggioService();
SimpleDateFormat dateformat = null;
if(this.debug) {
dateformat = DateUtils.getSimpleDateFormatMs();
}
// MESSAGGIO BASE
File fDump = null;
DumpMessaggio dumpMessaggio = new DumpMessaggio();
dumpMessaggio.setProtocollo(protocollo);
dumpMessaggio.setIdTransazione(idTransazione);
dumpMessaggio.setServizioApplicativoErogatore(servizioApplicativoErogatore);
dumpMessaggio.setDataConsegnaErogatore(dataConsegnaErogatore);
dumpMessaggio.setTipoMessaggio(tipoMessaggio);
if(this.debug){
this.log.debug("formato-messaggio: "+formatoMessaggio);
this.log.debug("gdo: "+dateformat.format(gdo));
this.log.debug("content-type["+messaggio.getContentType()+"]");
if(messaggio.getBody()==null) {
this.log.debug("body undefined");
}
else {
this.log.debug("body: "+Utilities.convertBytesToFormatString(messaggio.getBody().size()));
}
}
if(formatoMessaggio!=null) {
dumpMessaggio.setFormatoMessaggio(formatoMessaggio.name());
}
dumpMessaggio.setDumpTimestamp(gdo);
dumpMessaggio.setContentType(messaggio.getContentType());
if(messaggio.getBody()!=null && messaggio.getBody().size()>0) {
if(!messaggio.getBody().isSerializedOnFileSystem()) {
dumpMessaggio.setBody(messaggio.getBody().toByteArray());
dumpMessaggio.setContentLength(Long.valueOf(messaggio.getBody().size()));
}
else {
fDump = messaggio.getBody().getSerializedFile();
dumpMessaggio.setContentLength(fDump.length());
}
}
if(messaggio.getBodyMultipartInfo()!=null) {
if(this.debug){
this.log.debug("multipart-body-content-id["+messaggio.getBodyMultipartInfo().getContentId()+"]");
this.log.debug("multipart-body-content-location["+messaggio.getBodyMultipartInfo().getContentLocation()+"]");
this.log.debug("multipart-body-content-type["+messaggio.getBodyMultipartInfo().getContentType()+"]");
}
dumpMessaggio.setMultipartContentId(messaggio.getBodyMultipartInfo().getContentId());
dumpMessaggio.setMultipartContentLocation(messaggio.getBodyMultipartInfo().getContentLocation());
dumpMessaggio.setMultipartContentType(messaggio.getBodyMultipartInfo().getContentType());
if(messaggio.getBodyMultipartInfo().getHeaders()!=null &&
messaggio.getBodyMultipartInfo().getHeaders().size()>0) {
if(this.debug){
this.log.debug("Dump "+messaggio.getBodyMultipartInfo().getHeaders().size()+" multipart-body headers");
}
Map<String, List<String>> propertiesHdr = new HashMap<>();
List<DumpMultipartHeader> backupFailed = new ArrayList<DumpMultipartHeader>();
Iterator<String> keys = messaggio.getBodyMultipartInfo().getHeaders().keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
List<String> values = messaggio.getBodyMultipartInfo().getHeaders().get(key);
if(values!=null && !values.isEmpty()) {
for (String value : values) {
if(value==null){
value = ""; // puo' succedere in alcuni casi.
}
if(this.debug){
this.log.debug("\t\t"+key+"="+value);
}
DumpMultipartHeader headerMultipart = new DumpMultipartHeader();
headerMultipart.setNome(key);
headerMultipart.setValore(value.toString());
headerMultipart.setDumpTimestamp(gdo);
if(headersCompact) {
TransportUtils.addHeader(propertiesHdr, key, value);
backupFailed.add(headerMultipart);
}
else {
dumpMessaggio.addMultipartHeader(headerMultipart);
}
}
}
}
if(headersCompact) {
PropertiesSerializator ps = new PropertiesSerializator(propertiesHdr);
try{
dumpMessaggio.setMultipartHeaderExt(ps.convertToDBColumnValue());
backupFailed.clear();
backupFailed = null;
}catch(Throwable e){
// NOTA: questo metodo dovrebbe non lanciare praticamente mai eccezione
this.log.error("Errore durante la conversione degli header multipart: "+e.getMessage(),e);
for (DumpMultipartHeader dumpMultipartHeader : backupFailed) {
dumpMessaggio.addMultipartHeader(dumpMultipartHeader);
}
}
}
}
}
dumpMessaggio.setPostProcessed(1);
// HEADER TRASPORTO
if(messaggio.getHeaders()!=null && messaggio.getHeaders().size()>0){
if(this.debug){
this.log.debug("Dump "+messaggio.getHeaders().size()+" headers");
}
Map<String, List<String>> propertiesHdr = new HashMap<>();
List<DumpHeaderTrasporto> backupFailed = new ArrayList<DumpHeaderTrasporto>();
Iterator<String> keys = messaggio.getHeaders().keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
List<String> values = messaggio.getHeaders().get(key);
if(values!=null && !values.isEmpty()) {
for (String value : values) {
if(value==null){
value = ""; // puo' succedere in alcuni casi.
}
if(this.debug){
this.log.debug("\t\t"+key+"="+value);
}
DumpHeaderTrasporto headerTrasporto = new DumpHeaderTrasporto();
headerTrasporto.setNome(key);
headerTrasporto.setValore(value.toString());
headerTrasporto.setDumpTimestamp(gdo);
if(headersCompact) {
TransportUtils.addHeader(propertiesHdr,key, value);
backupFailed.add(headerTrasporto);
}
else {
dumpMessaggio.addHeaderTrasporto(headerTrasporto);
}
}
}
}
if(headersCompact) {
PropertiesSerializator ps = new PropertiesSerializator(propertiesHdr);
try{
dumpMessaggio.setHeaderExt(ps.convertToDBColumnValue());
backupFailed.clear();
backupFailed = null;
}catch(Throwable e){
// NOTA: questo metodo dovrebbe non lanciare praticamente mai eccezione
this.log.error("Errore durante la conversione degli header: "+e.getMessage(),e);
for (DumpHeaderTrasporto dumpHeader : backupFailed) {
dumpMessaggio.addHeaderTrasporto(dumpHeader);
}
}
}
}
// ALLEGATI
if(messaggio.getAttachments()!=null && messaggio.getAttachments().size()>0) {
if(this.debug){
this.log.debug("Dump "+messaggio.getAttachments().size()+" attachments");
}
for (Attachment attach : messaggio.getAttachments()) {
if(this.debug){
this.log.debug("Attachment:");
this.log.debug("\t\tId["+attach.getContentId()+"]");
this.log.debug("\t\tlocation["+attach.getContentLocation()+"]");
this.log.debug("\t\ttype["+attach.getContentType()+"]");
if(attach.getContent()==null) {
this.log.debug("\t\tcontent undefined");
}
else {
this.log.debug("\t\tcontent: "+Utilities.convertBytesToFormatString(attach.getContent().length));
}
}
DumpAllegato dumpAllegato = new DumpAllegato();
dumpAllegato.setContentId(attach.getContentId());
dumpAllegato.setContentLocation(attach.getContentLocation());
dumpAllegato.setContentType(attach.getContentType());
dumpAllegato.setAllegato(attach.getContent());
dumpAllegato.setDumpTimestamp(gdo);
dumpMessaggio.addAllegato(dumpAllegato);
if(attach.getHeaders()!=null && attach.getHeaders().size()>0){
if(this.debug){
this.log.debug("Dump "+attach.getHeaders().size()+" headers dell'allegato con id ["+attach.getContentId()+"]");
}
Map<String, List<String>> propertiesHdr = new HashMap<>();
List<DumpHeaderAllegato> backupFailed = new ArrayList<DumpHeaderAllegato>();
Iterator<String> keys = attach.getHeaders().keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
List<String> values = attach.getHeaders().get(key);
if(values!=null && !values.isEmpty()) {
for (String value : values) {
if(value==null){
value = ""; // puo' succedere in alcuni casi.
}
if(this.debug){
this.log.debug("\t\t"+key+"="+value);
}
DumpHeaderAllegato headerAllegato = new DumpHeaderAllegato();
headerAllegato.setNome(key);
headerAllegato.setValore(value.toString());
headerAllegato.setDumpTimestamp(gdo);
if(headersCompact) {
TransportUtils.addHeader(propertiesHdr,key, value);
backupFailed.add(headerAllegato);
}
else {
dumpAllegato.addHeader(headerAllegato);
}
}
}
}
if(headersCompact) {
PropertiesSerializator ps = new PropertiesSerializator(propertiesHdr);
try{
dumpAllegato.setHeaderExt(ps.convertToDBColumnValue());
backupFailed.clear();
backupFailed = null;
}catch(Throwable e){
// NOTA: questo metodo dovrebbe non lanciare praticamente mai eccezione
this.log.error("Errore durante la conversione degli header dell'allegato '"+attach.getContentId()+"': "+e.getMessage(),e);
for (DumpHeaderAllegato dumpHeader : backupFailed) {
dumpAllegato.addHeader(dumpHeader);
}
}
}
}
}
}
// CONTENUTI
if(messaggio.getContenuti()!=null && messaggio.getContenuti().size()>0){
if(this.debug){
this.log.debug("Dump "+messaggio.getContenuti().size()+" contenuti");
}
Iterator<String> keys = messaggio.getContenuti().keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
String value = messaggio.getContenuti().get(key);
if(value==null){
value = ""; // puo' succedere in alcuni casi.
}
DumpContenuto contenuto = TransactionContentUtils.createDumpContenuto(key, value, gdo);
if(this.debug){
this.log.debug("\t\t"+key+"="+value);
}
dumpMessaggio.addContenuto(contenuto);
}
}
if(this.debug){
this.log.debug("@@ log"+identificativoDump+" registrazione in corso ...");
}
dumpMessageService.create(dumpMessaggio);
if(fDump!=null) {
ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.tipoDatabase);
sqlQueryObject.addUpdateTable(CostantiDB.DUMP_MESSAGGI);
sqlQueryObject.addUpdateField("body", "?");
sqlQueryObject.addWhereCondition(CostantiDB.DUMP_MESSAGGI+".id=?");
IJDBCAdapter jdbcAdapter = JDBCAdapterFactory.createJDBCAdapter(this.tipoDatabase);
String sqlQueryUpdate =sqlQueryObject.createSQLUpdate();
PreparedStatement pstmt = null;
try {
try(FileInputStream fin = new FileInputStream(fDump)){
int index = 1;
pstmt = con.prepareStatement(sqlQueryUpdate);
jdbcAdapter.setBinaryData(pstmt, index++, fin, true);
pstmt.setLong(index++, dumpMessaggio.getId());
pstmt.execute();
}
}finally {
try {
if(pstmt!=null) {
pstmt.close();
}
}catch(Exception eClose) {
// close
}
}
}
if(this.debug){
this.log.debug("@@ log"+identificativoDump+" registrazione completata");
}
}catch(Exception e){
throw new DumpException("Errore durante il dump del messaggio idTransazione["+idTransazione+"] tipoMessaggio["+tipoMessaggio+"]: "+e.getMessage(),e);
}finally{
try{
this.releaseConnection(cr, "dump.log");
}catch(Exception e){
// close
}
}
}
}