Riscontri.java
- /*
- * GovWay - A customizable API Gateway
- * https://govway.org
- *
- * Copyright (c) 2005-2025 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.engine.driver;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.List;
- import org.openspcoop2.protocol.engine.Configurazione;
- import org.openspcoop2.protocol.engine.constants.Costanti;
- import org.openspcoop2.protocol.sdk.ProtocolException;
- import org.openspcoop2.protocol.sdk.constants.ProfiloDiCollaborazione;
- import org.openspcoop2.protocol.sdk.state.IState;
- import org.openspcoop2.protocol.sdk.state.StateMessage;
- import org.openspcoop2.utils.LoggerWrapperFactory;
- import org.openspcoop2.utils.Utilities;
- import org.openspcoop2.utils.date.DateManager;
- import org.openspcoop2.utils.jdbc.JDBCUtilities;
- import org.openspcoop2.utils.sql.ISQLQueryObject;
- import org.openspcoop2.utils.sql.SQLObjectFactory;
- import org.slf4j.Logger;
- /**
- * Sono inclusi i metodi per la gestione dei Riscontri.
- * La gestione dei riscontri puo' essere classificati nella seguente maniera :
- * <ul>
- * <li> Riscontri da ricevere, dove un mittente ha inviato una busta e sta' attendendo un ACK!
- * <li> Riscontri da inviare (modalita' NON PIGGYBACKING), quando una porta di dominio riceve una busta
- * con profilo 'ConfermaRicezione'==true, deve generare un riscontro apposito.
- * <li> Riscontri da inviare (modalita' PIGGYBACKING), quando una porta di dominio riceve una busta
- * con profilo 'ConfermaRicezione'==true, deve salvarsi le informazioni per generare successivi riscontri.
- * </ul>
- * Tutti i metodi hanno bisogno di una connessione ad un DB, precedentemente impostata
- * e passata attraverso l'apposito metodo.
- *
- *
- * @author Poli Andrea (apoli@link.it)
- * @author Tronci Fabio (tronci@link.it)
- * @author $Author$
- * @version $Rev$, $Date$
- */
- public class Riscontri {
- /** Logger utilizzato per debug. */
- private Logger log = null;
-
- /** Se IState e' un'istanza di StatefulMessage possiede una Connessione SQL in autoCommit mode su cui effettuare query
- * Altrimenti, e' un'istanza di StatelessMessage e nn necessita di connessioni */
- private IState state;
- /* ******** C O S T R U T T O R E ******** */
- /**
- * Costruttore.
- *
- * @param state Oggetto che rappresenta lo stato di una busta
- *
- */
- public Riscontri(IState state){
- this(state,Configurazione.getLibraryLog());
- }
- /**
- * Costruttore.
- *
- * @param state Oggetto che rappresenta lo stato di una busta
- *
- */
- public Riscontri(IState state ,Logger alog){
- this.state = state;
- if(alog!=null){
- this.log = alog;
- }else{
- this.log = LoggerWrapperFactory.getLogger(Riscontri.class.getName());
- }
- }
- public void updateState(IState state) {
- this.state = state;
- }
-
- /* ******** R I S C O N T R I D A R I C E V E R E ******** */
- /**
- * Aggiunge un riscontro da ricevere nella tabella per la gestione della fase di ricezione riscontro.
- *
- * @param id identificativo della busta.
- * @param timestamp data di invio della busta.
- *
- */
- public void registraRiscontroDaRicevere(String id , Date timestamp)throws ProtocolException{
- StateMessage stateMSG = (StateMessage)this.state;
- Connection connectionDB = stateMSG.getConnectionDB();
-
- PreparedStatement pstmt = null;
-
- try{
- java.sql.Timestamp oraInvio = new java.sql.Timestamp(timestamp.getTime());
- StringBuilder query = new StringBuilder();
- query.append("INSERT INTO ");
- query.append(Costanti.RISCONTRI_DA_RICEVERE);
- query.append(" VALUES ( ? , ? )");
- pstmt = connectionDB.prepareStatement(query.toString());
- pstmt.setString(1,id);
- pstmt.setTimestamp(2,oraInvio);
- // Add PreparedStatement (LASCIARE UPDATE per ordine esecuzione)
- stateMSG.getPreparedStatement().put("UPDATE saveRiscontroDaRicevere_"+id,pstmt);
- // Registrazione nella tabella History
- History historyBuste = new History(this.state);
- historyBuste.registraBustaInviata(id);
-
- } catch(Exception e) {
- String errorMsg = "RISCONTRI, Errore di registrazione "+id+": "+e.getMessage();
- this.log.error(errorMsg,e);
- try{
- if( pstmt != null )
- pstmt.close();
- } catch(Exception er) {
- // Eccezione SQL.
- }
- throw new ProtocolException(errorMsg,e);
- }
- }
- /**
- * In caso esista nella tabella dei riscontri da ricevere, un riscontro scaduto,
- * si occupa di ritornare un array di riscontro da reinviare, aggiornando le loro data di registrazione.
- * Il controllo non e' serializzato, quindi possono essere ritornate anche busta gia' riscontrate, in seguito al controllo.
- *
- * @param timeout Minuti dopo il quale una data risulta scaduta.
- * @return un List di {@link org.openspcoop2.protocol.sdk.Busta} contenente le informazioni necessarie per il re-invio delle buste,
- * se esistono riscontro scaduti.
- */
- public List<BustaNonRiscontrata> getBustePerUlterioreInoltro(long timeout, int limit, int offset, boolean logQuery)throws ProtocolException{
-
- StateMessage stateMSG = (StateMessage)this.state;
- Connection connectionDB = stateMSG.getConnectionDB();
- PreparedStatement pstmt = null;
- ResultSet rs = null;
- java.util.List<String> IDBuste = new java.util.ArrayList<>();
- String queryString = null;
- try{
- long nowTime = DateManager.getTimeMillis() - (timeout * 60 * 1000);
- java.sql.Timestamp scadenzaRiscontro = new java.sql.Timestamp(nowTime);
- if(Configurazione.getSqlQueryObjectType()==null){
- StringBuilder query = new StringBuilder();
- query.append("SELECT ID_MESSAGGIO FROM ");
- query.append(Costanti.RISCONTRI_DA_RICEVERE);
- query.append(" WHERE DATA_INVIO < ? ");
- queryString = query.toString();
- }else{
- ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(Configurazione.getSqlQueryObjectType());
- sqlQueryObject.addSelectField("ID_MESSAGGIO");
- sqlQueryObject.addSelectField("DATA_INVIO");
- sqlQueryObject.addFromTable(Costanti.RISCONTRI_DA_RICEVERE);
- sqlQueryObject.addWhereCondition("DATA_INVIO < ?"); // order by e' obbligatorio essendoci l'offset
- sqlQueryObject.setANDLogicOperator(true);
- sqlQueryObject.addOrderBy("DATA_INVIO");
- sqlQueryObject.setSortType(true);
- sqlQueryObject.setLimit(limit);
- sqlQueryObject.setOffset(offset);
- queryString = sqlQueryObject.createSQLQuery();
- }
- //System.out.println("QUERY RISCONTRI IS: ["+queryString+"] 1["+scadenzaRiscontro+"]");
- pstmt = connectionDB.prepareStatement(queryString);
- pstmt.setTimestamp(1,scadenzaRiscontro);
- // Esecuzione comando SQL
- long startDateSQLCommand = DateManager.getTimeMillis();
- if(logQuery)
- this.log.debug("[QUERY] (Riscontri) ["+queryString+"] 1["+scadenzaRiscontro+"]...");
- rs = pstmt.executeQuery();
- long endDateSQLCommand = DateManager.getTimeMillis();
- long secondSQLCommand = (endDateSQLCommand - startDateSQLCommand) / 1000;
- if(logQuery)
- this.log.debug("[QUERY] (Riscontri) ["+queryString+"] 1["+scadenzaRiscontro+"] effettuata in "+secondSQLCommand+" secondi");
- if(rs == null) {
- pstmt.close();
- throw new ProtocolException("RS NULL?");
- }
- int countLimit = 0;
- int countOffset = 0;
- while(rs.next()){
- if(Configurazione.getSqlQueryObjectType()==null){
- // OFFSET APPLICATIVO
- if( countOffset>=offset ){
- String id = rs.getString("ID_MESSAGGIO");
- IDBuste.add(id);
- // LIMIT Applicativo
- countLimit++;
- if(countLimit==limit)
- break;
- }
- else{
- countOffset++;
- }
- }else{
- String id = rs.getString("ID_MESSAGGIO");
- IDBuste.add(id);
- }
- }
- rs.close();
- pstmt.close();
- } catch(Exception e) {
- try{
- if( rs != null )
- rs.close();
- } catch(Exception er) {
- // close
- }
- try{
- if( pstmt != null )
- pstmt.close();
- } catch(Exception er) {
- // close
- }
- String errorMsg = "[Riscontri.getBustePerUlterioreInoltro] errore, queryString["+queryString+"]: "+e.getMessage();
- this.log.error(errorMsg,e);
- throw new ProtocolException(errorMsg,e);
- }
-
-
- List<BustaNonRiscontrata> listaBustaNonRiscontrata = new ArrayList<BustaNonRiscontrata>();
- for (int i = 0; i < IDBuste.size(); i++) {
- BustaNonRiscontrata bustaNonRiscontrata = new BustaNonRiscontrata();
- bustaNonRiscontrata.setIdentificativo(IDBuste.get(i));
- bustaNonRiscontrata.setProfiloCollaborazione(ProfiloDiCollaborazione.ONEWAY);
- listaBustaNonRiscontrata.add(bustaNonRiscontrata);
- }
-
- return listaBustaNonRiscontrata;
-
- }
-
-
-
- /**
- * Valida un riscontro ricevuto, identificato dall'identificativo della busta.
- * In caso di validazione del riscontro, l'entry nella tabella di gestione dei riscontri da ricevere,
- * con chiave di accesso uguale al parametro <var>idRiscontro</var> viene cancellata.
- *
- * @param idRiscontro identificativo del riscontro da validare.
- * @deprecated utilizzare la versione non serializable
- */
- @Deprecated
- public void validazioneRiscontroRicevuto_serializable(String idRiscontro) throws ProtocolException{
- validazioneRiscontroRicevuto_serializable(idRiscontro,60l,100);
- }
- /**
- * Valida un riscontro ricevuto, identificato dall'identificativo della busta.
- * In caso di validazione del riscontro, l'entry nella tabella di gestione dei riscontri da ricevere,
- * con chiave di accesso uguale al parametro <var>idRiscontro</var> viene cancellata.
- *
- * @param idRiscontro identificativo del riscontro da validare.
- * @param attesaAttiva AttesaAttiva per la gestione del livello di serializable
- * @param checkInterval Intervallo di check per la gestione del livello di serializable
- * @deprecated utilizzare la versione non serializable
- */
- @Deprecated
- public void validazioneRiscontroRicevuto_serializable(String idRiscontro,long attesaAttiva,int checkInterval) throws ProtocolException{
- StateMessage stateMSG = (StateMessage)this.state;
- Connection connectionDB = stateMSG.getConnectionDB();
- /*
- Viene realizzato con livello di isolamento SERIALIZABLE, per essere sicuri
- che esecuzioni parallele non leggano dati inconsistenti.
- Con il livello SERIALIZABLE, se ritorna una eccezione, deve essere riprovato
- */
- // setAutoCommit e livello Isolamento
- int oldTransactionIsolation = -1;
- try{
- oldTransactionIsolation =connectionDB.getTransactionIsolation();
- connectionDB.setAutoCommit(false);
- JDBCUtilities.setTransactionIsolationSerializable(Configurazione.getSqlQueryObjectType(), connectionDB);
- } catch(Exception er) {
- String errorMsg = "RISCONTRI, Errore durante la validazioneRiscontroRicevuto(setIsolation): "+er.getMessage();
- this.log.error(errorMsg,er);
- throw new ProtocolException(errorMsg,er);
- }
- boolean deleteRiscontroOK = false;
- long scadenzaWhile = DateManager.getTimeMillis() + attesaAttiva;
- while(deleteRiscontroOK==false && DateManager.getTimeMillis() < scadenzaWhile){
- PreparedStatement pstmtDelete = null;
- try{
- // Eliminazione dalla tabella Riscontri
- StringBuilder query = new StringBuilder();
- query.delete(0,query.capacity());
- query.append("DELETE FROM ");
- query.append(Costanti.RISCONTRI_DA_RICEVERE);
- query.append(" WHERE ID_MESSAGGIO = ?");
- pstmtDelete = connectionDB.prepareStatement(query.toString());
- pstmtDelete.setString(1,idRiscontro);
- pstmtDelete.execute();
- pstmtDelete.close();
- // Eliminazione dalla tabella History
- History historyBuste = new History(this.state,this.log);
- historyBuste.eliminaBustaInviata(idRiscontro);
-
- stateMSG.executePreparedStatement();
- // Chiusura Transazione
- connectionDB.commit();
- // ID Costruito
- deleteRiscontroOK = true;
- } catch(Exception e) {
- try{
- if( pstmtDelete != null )
- pstmtDelete.close();
- } catch(Exception er) {
- // close
- }
- try{
- connectionDB.rollback();
- } catch(Exception er) {
- // ignore
- }
- }
- if(deleteRiscontroOK == false){
- // Per aiutare ad evitare conflitti
- try{
- Utilities.sleep(ProtocolRandomUtilities.getRandom().nextInt(checkInterval)); // random da 0ms a checkIntervalms
- }catch(Exception eRandom){
- // ignore
- }
- }
- }
- // Ripristino Transazione
- try{
- connectionDB.setTransactionIsolation(oldTransactionIsolation);
- connectionDB.setAutoCommit(true);
- } catch(Exception er) {
- String errorMsg = "RISCONTRI, Errore durante la validazioneRiscontroRicevuto(ripristinoIsolation): "+er.getMessage();
- this.log.error(errorMsg,er);
- throw new ProtocolException(errorMsg,er);
- }
- }
- /**
- * Valida un riscontro ricevuto, identificato dall'identificativo della busta.
- * In caso di validazione del riscontro, l'entry nella tabella di gestione dei riscontri da ricevere,
- * con chiave di accesso uguale al parametro <var>idRiscontro</var> viene cancellata.
- *
- * @param idRiscontro identificativo del riscontro da validare.
- */
- public void validazioneRiscontroRicevuto(String idRiscontro) throws ProtocolException{
-
- StateMessage stateMSG = (StateMessage)this.state;
- Connection connectionDB = stateMSG.getConnectionDB();
- PreparedStatement pstmtDelete = null;
- try{
- // Eliminazione dalla tabella Riscontri
- StringBuilder query = new StringBuilder();
- query.delete(0,query.capacity());
- query.append("DELETE FROM ");
- query.append(Costanti.RISCONTRI_DA_RICEVERE);
- query.append(" WHERE ID_MESSAGGIO = ?");
- pstmtDelete = connectionDB.prepareStatement(query.toString());
- pstmtDelete.setString(1,idRiscontro);
- // Add PreparedStatement (LASCIARE UPDATE per ordine esecuzione)
- stateMSG.getPreparedStatement().put("UPDATE validazioneRiscontroRicevuto_"+idRiscontro,pstmtDelete);
- // Eliminazione dalla tabella History
- History historyBuste = new History(stateMSG,this.log);
- historyBuste.eliminaBustaInviataPerRiscontri(idRiscontro);
- } catch(Exception e) {
- try{
- if( pstmtDelete != null )
- pstmtDelete.close();
- } catch(Exception er) {
- // close
- }
- String errorMsg = "RISCONTRI, Errore durante la validazioneRiscontroRicevuto: "+e.getMessage();
- this.log.error(errorMsg,e);
- throw new ProtocolException(errorMsg,e);
- }
- }
- }